使用選項表示函式的失敗

在 C++ 17 之前,函式通常以下列幾種方式之一表示失敗:

  • 返回了一個空指標。
    • 例如,在沒有委託的 App 例項上呼叫函式 Delegate *App::get_delegate() 將返回 nullptr
    • 對於動態分配或大型並由指標管理的物件,這是一個很好的解決方案,但對於通常通過複製進行堆疊分配和傳遞的小物件來說,這不是一個好的解決方案。
  • 保留返回型別的特定值以指示失敗。
    • 例如,在兩個未連線的頂點上呼叫函式 unsigned shortest_path_distance(Vertex a, Vertex b) 可能會返回零以指示此事實。
  • 該值與 bool 配對,表示返回的值是有意義的。
    • 例如,使用不是整數的字串引數呼叫函式 std::pair<int, bool> parse(const std::string &str) 將返回一個未定義 intbool 設定為 false 的對。

在這個例子中,John 給了兩隻寵物,Fluffy 和 Furball。然後呼叫函式 Person::pet_with_name() 來檢索 John 的寵物鬍鬚。由於 John 沒有名為 Whiskers 的寵物,因此該功能失敗並返回 std::nullopt

#include <iostream>
#include <optional>
#include <string>
#include <vector>

struct Animal {
    std::string name;
};

struct Person {
    std::string name;
    std::vector<Animal> pets;
    
    std::optional<Animal> pet_with_name(const std::string &name) {
        for (const Animal &pet : pets) {
            if (pet.name == name) {
                return pet;
            }
        }
        return std::nullopt;
    }
};

int main() {
    Person john;
    john.name = "John";
    
    Animal fluffy;
    fluffy.name = "Fluffy";
    john.pets.push_back(fluffy);
    
    Animal furball;
    furball.name = "Furball";
    john.pets.push_back(furball);
    
    std::optional<Animal> whiskers = john.pet_with_name("Whiskers");
    if (whiskers) {
        std::cout << "John has a pet named Whiskers." << std::endl;
    }
    else {
        std::cout << "Whiskers must not belong to John." << std::endl;
    }
}