从另一个 std::optional 和其他东西初始化 std::optional 的惯用方法

Idiomatic way to initialise std::optional from another std::optional and something else

本文关键字:std optional 方法 初始化 其他 另一个      更新时间:2023-10-16

我想初始化另一个std::optionalstd::optional和一些额外的参数,前提是后一个std::optional不为空。不幸的是std::optional::optional 4)和5)不适合,因为参数的数量不同。

我能够想出以下内容,但仍然感觉过分。我特别不喜欢显式指定 lambda 的返回类型。

有没有更好的(如更简洁和更具表现力)的方式来实现这一目标?

#include <iostream>
#include <optional>
#include <tuple>
struct A {
    A(std::optional<int> oi, float f, char c)
    :
        val{
            [&] () -> decltype(val) /* I don't like specifying type here */ {
                if (oi)
                    return {{*oi, f, c}};
                else
                    return std::nullopt;            
            }()
        }
    {
    }
    std::optional<std::tuple<int, float, char>> val;
};
int main()
{
    auto print = [](auto& r) {
        if (r)
            std::cout
                << std::get<0>(*r) << "; "
                << std::get<1>(*r) << "; "
                << std::get<2>(*r) << std::endl;
        else
            std::cout << "nullopt" << std::endl;
    };
    auto one = A({}, 1.0, 'c');
    print(one.val);
    auto two = A(10, 2.0, 'c');
    print(two.val);
}

活生生的例子。

只要相信编译器会做正确的事情:

A(std::optional<int> oi, float f, char c) {
    if (oi) {
        val.emplace(*oi, f, c);
    }
}

当然,这也是 map() 成员函数的一个很好的用例,您可以将其编写为非成员函数:

A(std::optional<int> oi, float f, char c)
    : val(map(oi, [&](int i){ return std::tuple(i, f, c); }))
{ }
<小时 />

最近由TartanLlama在P0798中提出。