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.

相关推荐
mengzhi啊3 小时前
QPluginLoader 动态 DLL 插件版,支持插件之间通信,广播。请求和应答
c++·qt
脉动数据行情13 小时前
C# 实现德指 DAX 期货 WebSocket 实时行情监听
开发语言·websocket·c#
大圣编蚕4 小时前
Java ByteArrayInputStream 详解:从入门到实战
java·开发语言·算法
菜鸟~noob2334 小时前
【电子战】第02篇:能量检测器 vs. 相关检测器【含matlab代码】
开发语言·matlab
OpenAnolis小助手5 小时前
一句话看透 JVM,SysOM 诊断 Skill 新增 Java 应用诊断能力
java·开发语言·jvm·阿里云·操作系统控制台·sysom
小玮看世界5 小时前
[Python]OD算法在OD实际运用转化参考清单
开发语言·python·算法
ForteScarlet5 小时前
Kotlin 2.4.20 现已发布,新特性多不多?
android·java·开发语言·开源·kotlin·jetbrains
萧瑟余晖5 小时前
Java深入解析篇六十二之安全机制详解
java·开发语言
老赵的博客6 小时前
c++ QT之动态库加载问题
c++·qt
菜鸟~noob2336 小时前
【电子战】 第01篇:噪声、门限与虚警/检测概率(PFA/PD)【含matlab代码】
开发语言·matlab