使用选项表示函数的失败

在 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;
    }
}