std::optional新增transform and_then or_else

std::optional 在C++23中新增了一些支持链式调用的函数:

三个函数最终都返回optiona,只是F函数的返回值可能不一样。

transform(F): 如果*this有值, 则返回F的结果(F返回不一定是optional<U>类型,其他不是optional都可以), 否则返回空的optional.

and_then(F): 如果*this有值, 则返回F的结果(F必须返回optional<U>类型), 否则返回空的optional.

or_else(F): 如果*this有值, 则返回*this, 否则返回F的结果(F必须返回optional<U>类型).

 

  • transform:对值进行转换,保持 optional 结构。
  • and_then:链式调用可能失败的操作,自动处理空值。
  • or_else:为空时提供备用值或恢复逻辑。

std::optional<T>::transform

 

If *this contains a value, invokes f with the contained value as an argument, and returns an std::optional that contains the result of that invocation; otherwise, returns an empty std::optional.

  • 功能:若 optional 有值,则应用给定函数到该值,返回包装结果的 optional;否则返回空 optional
  • F的返回值不一定是optional的。

 

#include <optional>
#include <iostream>

int foo(int x)
{
    return x*2;
}

int main() 
{
    std::optional<int> o1 = 42;
    auto doubled = o1.transform(foo); // 返回 std::optional<int> 包含 84

    std::optional<int> o2;
    auto empty = o2.transform([](int n) { return n * 2; }); // 返回空 optional

    std::cout << doubled.value_or(0) << ", " << empty.value_or(0) << std::endl; // 输出: 84, 0
}

链式di 

​
#include <iostream>
#include <optional>
 
struct A { /* ... */ };
struct B { /* ... */ };
struct C { /* ... */ };
struct D { /* ... */ };
 
auto A_to_B(A) -> B { /* ... */ std::cout << "A => B \n"; return {}; }
auto B_to_C(B) -> C { /* ... */ std::cout << "B => C \n"; return {}; }
auto C_to_D(C) -> D { /* ... */ std::cout << "C => D \n"; return {}; }
 
void try_transform_A_to_D(std::optional<A> o_A)
{
    std::cout << (o_A ? "o_A has a value\n" : "o_A is empty\n");
 
    std::optional<D> o_D = o_A.transform(A_to_B)
                              .transform(B_to_C)
                              .transform(C_to_D);
 
    std::cout << (o_D ? "o_D has a value\n\n" : "o_D is empty\n\n");
};
 
int main()
{
    try_transform_A_to_D( A{} );
    try_transform_A_to_D( {} );
}

​

Output:

o_A has a value
A => B
B => C
C => D
o_D has a value
 
o_A is empty
o_D is empty

 

std::optional<T>::and_then

If *this contains a value, invokes f with the contained value as an argument, and returns the result of that invocation; otherwise, returns an empty std::optional.

The return type (see below) must be a specialization of std::optional (unlike transform()). Otherwise, the program is ill-formed.

  • 功能:若 optional 有值,则应用返回 optional 的函数,并直接返回该结果(展平嵌套);否则返回空。
  • f返回值必须是optional<T>的

 

#include <optional>
#include <string>

std::optional<std::string> int_to_str(int n) 
{
    if (n >= 0) return std::to_string(n);
    else return std::nullopt;
}

int main() 
{
    std::optional<int> o1 = 10;
    auto str1 = o1.and_then(int_to_str); // 返回 std::optional<std::string> 包含 "10"

    std::optional<int> o2 = -5;
    auto str2 = o2.and_then(int_to_str); // 返回空 optional

    std::optional<int> o3;
    auto str3 = o3.and_then(int_to_str); // 返回空 optional
}

std::optional<T>::or_else

Returns *this if it contains a value. Otherwise, returns the result of f.

  • 功能:若 optional 为空,则调用给定函数生成替代的 optional;否则返回原值。
  • F返回值必须是optional<T>的
#include <iostream>
#include <optional>
#include <string>

int main()
{
    using maybe_int = std::optional<int>;
    
    auto valuesless = []
    {
        std::cout << "Valueless: ";
        return maybe_int{0};
    };
    
    maybe_int x;
    std::cout << x.or_else(valuesless).value() << std::endl;
    
    x = 42;
    std::cout << x.or_else(valuesless).value() << std::endl;
    
    x.reset();
    std::cout << x.or_else(valuesless).value() << std::endl;
}
​

Output:

Valueless: 0
Has value: 42
Valueless: 0

综合示例:

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

std::optional<std::string> get_input(bool valid) 
{
    return valid ? std::optional{"42"} : std::nullopt;
}

std::optional<int> parse(const std::string& s) 
{
    try 
    {
        return std::stoi(s);
    } 
    catch (...) 
    {
        return std::nullopt;
    }
}

int main()
{
    // 有效输入
    auto result1 = get_input(true)
        .and_then(parse)            // 返回 optional<int> 42
        .transform([](int n) { return n * 2; }) // 返回 optional<int> 84
        .or_else([] { return std::optional<int>(0); }); // 仍为 84

    // 无效输入
    auto result2 = get_input(false)
        .and_then(parse)            // 返回空
        .transform([](int n) { return n * 2; }) // 仍为空
        .or_else([] { return std::optional<int>(0); }); // 返回 0

    std::cout << result1.value() << ", " << result2.value() << std::endl; // 输出: 84, 0
}

### 不同点

1. **返回类型**:

    - `transform`:应用的函数返回一个值,`transform` 返回一个包含该值的 `std::optional`。

    - `and_then`:应用的函数返回一个 `std::optional`,`and_then` 返回这个新的 `std::optional`。

2. **适用场景**:

    - `transform`:适用于需要对 `std::optional` 中的值进行转换,并且转换后的结果不需要是 `std::optional` 的场景。

    - `and_then`:适用于需要对 `std::optional` 中的值进行转换,并且转换后的结果也是 `std::optional` 的场景。

这两个函数提供了更灵活和简洁的方式来处理 `std::optional` 中的值。

Eg1:

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

using namespace std;

optional<int> Parse(const string& s) 
{
    try 
    {
        return stoi(s);
    } 
    catch (...)
    {
        return {};
    }
}

int main() 
{
    vector<string> inputs{"12", "nan"};

    for (auto& s : inputs)
    {
        std::cout << s << std::endl;
        auto result =

#if 1
        Parse(s)
            .and_then([](int value) -> optional<int> { std::cout << "call and_then, "; return value * 2; })
            .transform([](int value) { std::cout << "call transform, "; return to_string(value); })
            .or_else([] { return optional<string>{"No Integer Found"}; });
#else     
        Parse(s)
            .and_then([](int value) -> optional<string> { std::cout << "call and_then, "; return to_string(value * 2); }) //不能没有optional,跟transform的区别;
            .transform([](std::string value) { std::cout << "call transform, "; return value; })
            .or_else([] { return optional<string>{"No Integer Found"}; });
#endif

        cout << *result << endl << std::endl;
    }
}

Eg2:

#include <charconv>
#include <iomanip>
#include <iostream>
#include <optional>
#include <ranges>
#include <string>
#include <string_view>
#include <vector>

std::optional<int> to_int(std::string_view sv)
{
    int r{};
    auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), r);
    if (ec == std::errc{})
        return r;
    else
        return std::nullopt;
}

int main()
{
    using namespace std::literals;

    const std::vector<std::optional<std::string>> v
    {
        "1234", "15 foo", "bar", "42", "5000000000", " 5", std::nullopt, "-43"
    };

    for (auto&& x : v | std::views::transform(
        [](auto&& o)
        {
            // debug print the content of input optional<string>
            std::cout << std::left << std::setw(13)
                      << std::quoted(o.value_or("nullopt")) << " -> ";

            return o
                // if optional is nullopt convert it to optional with "" string
                .or_else([]{ return std::optional<std::string>{""}; })
                // flatmap from strings to ints (making empty optionals where it fails)
                .and_then(to_int)
                // map int to int + 1
                .transform([](int n) { return n + 1; })
                // convert back to strings
                .transform([](int n) { return std::to_string(n); })
                // replace all empty optionals that were left by
                // and_then and ignored by transforms with "NaN"
                .value_or("NaN"s);
        }))
    {
        std::cout << x << '\n';
    }
}

基于深度学习CNN网络+pytorch框架实现遥感图像滑坡识别源码+数据集+训练好的模型,个人经导师指导并认可通过的高分设计项目,评审分99分,代码完整确保可以运行,小白也可以亲自搞定,主要针对计算机相关专业的正在做大作业的学生和需要项目实战练习的学习者,可作为毕业设计、课程设计、期末大作业,代码资料完整,下载可用。 基于深度学习CNN网络+pytorch框架实现遥感图像滑坡识别源码+数据集+训练好的模型基于深度学习CNN网络+pytorch框架实现遥感图像滑坡识别源码+数据集+训练好的模型基于深度学习CNN网络+pytorch框架实现遥感图像滑坡识别源码+数据集+训练好的模型基于深度学习CNN网络+pytorch框架实现遥感图像滑坡识别源码+数据集+训练好的模型基于深度学习CNN网络+pytorch框架实现遥感图像滑坡识别源码+数据集+训练好的模型基于深度学习CNN网络+pytorch框架实现遥感图像滑坡识别源码+数据集+训练好的模型基于深度学习CNN网络+pytorch框架实现遥感图像滑坡识别源码+数据集+训练好的模型基于深度学习CNN网络+pytorch框架实现遥感图像滑坡识别源码+数据集+训练好的模型基于深度学习CNN网络+pytorch框架实现遥感图像滑坡识别源码+数据集+训练好的模型基于深度学习CNN网络+pytorch框架实现遥感图像滑坡识别源码+数据集+训练好的模型基于深度学习CNN网络+pytorch框架实现遥感图像滑坡识别源码+数据集+训练好的模型基于深度学习CNN网络+pytorch框架实现遥感图像滑坡识别源码+数据集+训练好的模型基于深度学习CNN网络+pytorch框架实现遥感图像滑坡识别源码+数据集+训练好的模型基于深度学习CNN网络+pytorch框架实现遥感图像滑坡识别源码+数据集+训练好的模型基于深度学习CNN网络+pytorch框架实现
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值