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.

相关推荐
H.莓飛9 小时前
【数据结构】排序_OJ题(一):计数、桶与排序后的处理
java·开发语言·数据结构
wangchunyu1149 小时前
JAVA AQS与Lock实现原理(含CAS)
java·开发语言·word
爱喝水的鱼丶10 小时前
SAP-ABAP:ECC→S/4HANA ABAP 迁移升级指南——程序改造、语法兼容与性能优化 导语
运维·开发语言·性能优化·sap·abap·经验交流·开发交流
小灰灰搞电子11 小时前
Rust+Slint 实现FTP客户端调试助手源码分享
开发语言·后端·rust
外收内放11 小时前
面向对象高级(实战案例)
开发语言·python·学习
·present·11 小时前
CSAPP(lecture 4_01)
c语言·c++
FPGA小迷弟11 小时前
用 Claude Code 重构遗留系统:从评估到落地的完整实践指南
c++·python·ai·plotly·django·ai编程·claude
fanruitian12 小时前
python else用法
开发语言·python
程序员-King.12 小时前
【ROS1】Noetic 开发工作流程与常用命令
c++·ubuntu·ros
FRing0312 小时前
JavaScript入门到精通二十六(变量提升、函数剩余参数、展开运算符、ES6箭头函数)
开发语言·前端·javascript·es6·箭头函数