c++ Expected用法

std::expected用于处理"可能失败的操作",表示一个操作要么成功并返回一个值,要么失败并返回一个错误信息。结合了类型安全和错误处理的优点,可以替代传统错误码和异常。

测试下:

cpp 复制代码
#include <expected>

// 返回成功时的 int,或失败时的 std::string 错误信息
static std::expected<int, std::string> divide(int a, int b) {
    if (b == 0) {
        return std::unexpected("Division by zero");
    }
    return a / b;
}

void testExpected(void) {
    auto result = divide(10, 0);

    // 判断是否有值
    if (result.has_value()) { // 可简写为 if (result)
        std::cout << "10 / 0 , Result: " << result.value() << "\n";
    } else {
        // 获取具体的错误信息
        std::cout << "Error: " << result.error() << "\n";
    }

    // 提供默认值
    int val = result.value_or(0); 
    std::cout << "val: " << val << std::endl;
}

运行:

ok. 还支持链式调用,比较方便。再测试下模拟登录:

cpp 复制代码
// 模拟用户
struct User {
    std::string name;
    std::string password;
};

// 步骤 1: 查找用户
static std::expected<User, std::string> find_user(const std::string& username) {
    if (username == "admin") {
        return User{"admin", "123456"};
    }
    return std::unexpected("User not found: " + username);
}

// 步骤 2: 验证密码
static std::expected<User, std::string> validate_password(const User& user, const std::string& pwd) {
    if (user.password == pwd) {
        return user; // 验证通过,返回用户
    }
    return std::unexpected("Invalid password for user: " + user.name);
}

// 步骤 3: 生成 Token (使用 transform 进行值的转换)
static std::expected<std::string, std::string> generate_token(const User& user) {
    return "Token_" + user.name + "_abc123";
}

// 测试链式调用
static void test_chained_login(const std::string& username, const std::string& pwd) {
    std::cout << "--- Testing login for: " << username << " ---" << std::endl;

    auto result = find_user(username)
        .and_then([&pwd](const User& user) { // and_then的参数是一个Lambda 表达式
            return validate_password(user, pwd); 
        }) // 这里还可以加or_else处理失败场景,试着抢救一下错误。
        .transform([](const User& user) { 
            // transform 的 lambda 直接返回普通值,而不是 expected
            return "Token_" + user.name + "_abc123";
        });

    // 统一处理最终结果
    if (result) {
        std::cout << "Login Success! Token: " << result.value() << "\n";
    } else {
        std::cout << "Login Failed! Error: " << result.error() << "\n";
    }
}


void testExpected2(void) {
    test_chained_login("admin", "123456"); 
    test_chained_login("guest", "123456"); 
    test_chained_login("admin", "wrong");
}

运行:

ok . 想修改下demo,测试下调用or_else。 如果校验密码不通过,但发现对方是女生,则让她通过。

user加一个性别字段:

cpp 复制代码
struct User {
    std::string name;
    std::string password;
    std::string gender; // "male" 或 "female"
};

修改find_user, 假设admin用户是女生:

cpp 复制代码
static std::expected<User, std::string> find_user(const std::string& username) {
    if (username == "admin") {
        return User{"admin", "123456", "female"};
    }
    return std::unexpected("User not found: " + username);
}

修改执行流程,加上密码校验失败时的or_else处理:

cpp 复制代码
static void test_chained_login2(const std::string& username, const std::string& pwd) {
    std::cout << "--- Testing login for: " << username << " ---" << std::endl;

    // 1. 先拿到 find_user 的结果
    auto user_result = find_user(username);

    // 2. 开始链式调用
    auto result = user_result
        .and_then([&](const User& user) { 
            return validate_password(user, pwd); 
        })
        .or_else([&](const std::string& err) -> std::expected<User, std::string> { // 注意,这个lambda表达式需要显式指定返回值类型,否则推导失败,报错:inconsistent types 'std::expected<User, std::__cxx11::basic_string<char> >' and 'std::unexpected<std::__cxx11::basic_string<char> >' deduced for lambda return type
            std::cout << ">>> 密码校验失败,触发 or_else 抢救机制...\n";
            if (user_result.has_value() && user_result->gender == "female") {
                std::cout << ">>> 发现是女生,热烈欢迎!\n";
                return std::expected<User, std::string>(user_result.value());
            }
            
            std::cout << ">>> 不是女生,继续拦截。\n";
            return std::unexpected<std::string>(err);
        })
        .transform([](const User& user) { 
            return "Token_" + user.name + "_abc123"; 
        });

    if (result) {
        std::cout << "Login Success! Token: " << result.value() << "\n\n";
    } else {
        std::cout << "Login Failed! Error: " << result.error() << "\n\n";
    }
}


void testExpected2(void) {
    // test_chained_login("admin", "123456"); 
    // test_chained_login("guest", "123456"); 
    // test_chained_login("admin", "wrong");

    test_chained_login2("admin", "mimi");
}

测试:

ok.

相关推荐
ch.ju1 小时前
Java程序设计(第3版)第四章——final修饰的方法和类
java·开发语言
极***技1 小时前
2026云原生核心!Go高并发限流实战,从原理到落地
开发语言·云原生·golang
牛大了20232 小时前
场景题:数据迁移解决方案
开发语言
王老师青少年编程10 小时前
2026年6月GESP真题及题解(C++一级):交税
c++·题解·真题·gesp·一级·2026年6月·交税
认真的酒窝10 小时前
自己动手开发编译器(十一)语义分析
java·开发语言
wbs_scy11 小时前
Linux C++ 高并发编程:线程池全链路深度解析,从原理到手撕实现
java·开发语言
JAVA面经实录91711 小时前
Linux 常用命令完整知识体系
java·linux·开发语言·汇编
贪玩的蛋挞12 小时前
C#与闭包
开发语言·c#
端庄的战斗机12 小时前
javascript 设计模式(文章很长,请自备瓜子,水果和眼药水)
开发语言·javascript·设计模式