使用?:运算符返回可选值

MiP*_*MiP 17 c++ optional c++17

我经常需要为函数使用可选类型:

std::optional<int32_t> get(const std::string& field)
{
    auto it = map.find(field);
    if (it != map.end()) return it->second;
    return {};
}
Run Code Online (Sandbox Code Playgroud)

有没有办法在一行中返回可选值?例如:

std::optional<int32_t> get(const std::string& field)
{
    auto it = map.find(field);
    return it != map.end() ? it->second : {};
}
Run Code Online (Sandbox Code Playgroud)

导致错误

error: expected primary-expression before '{' token
return it != map.end() ? it->second : {};
                                      ^
Run Code Online (Sandbox Code Playgroud)

dfr*_*fri 27

您可以显式地将some-value返回值包装为a std::optional,然后返回到constexpr std::nulloptno-value返回值.

std::nullopt:

std::nullopt是一个类型的常量,std::nullopt_t用于表示具有未初始化状态的可选类型.

...

std::nullopt_t:

std::nullopt_t是一个空类类型,用于指示具有未初始化状态的可选类型.特别是,std::optional有一个构造函数nullopt_t作为单个参数,它创建一个不包含值的可选项.

使用这种方法,三元运算符调用的true子句显式返回std::optional带有some值的,因此编译器可以int32_t从提供的包装值的类型推导出模板参数/包装类型(在本例中:),这意味着你需要不明确指定它.

适用于您的示例:

return it != map.end() ? std::optional(it->second) : std::nullopt;

// alternatively
return it != map.end() ? std::make_optional(it->second) : std::nullopt;
Run Code Online (Sandbox Code Playgroud)


Bau*_*gen 20

return it != map.end() ? it->second : std::optional<int32_t>{};
Run Code Online (Sandbox Code Playgroud)

应该做的伎俩.

编译器必须从最后两个操作数推导出三元表达式的结果类型,但是它无法std::optional<int32_t>int32_t和推导出{}.

int32_tstd::optional<int32_t>另一方面确实有所需的共同类型std::optional<int32_t>.


相关有趣的事实:您可以避免重复使用自动返回类型扣除的类型:

auto get(const std::string& field)
{
    auto it = map.find(field);
    return it != map.end() ? it->second : std::optional<int32_t>{};
}
Run Code Online (Sandbox Code Playgroud)

根据偏好,您当然也可以推断std::optionalfrom 的模板参数it->second,decltype以进一步减少重复.