Return Optional value with ?: operator

最后都变了- 提交于 2019-12-04 17:07:36

问题


I often need to use optional type for functions:

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

Is there a way to return optional value in one line? e.g. this:

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

results in the error

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

回答1:


You can explicitly wrap the some-value return into an std::optional, and fall back on the constexpr std::nullopt for the no-value return.

std::nullopt:

std::nullopt is a constant of type std::nullopt_t that is used to indicate optional type with uninitialized state.

...

std::nullopt_t:

std::nullopt_t is an empty class type used to indicate optional type with uninitialized state. In particular, std::optional has a constructor with nullopt_t as a single argument, which creates an optional that does not contain a value.

With this approach, the true clause of the ternary operator call explicitly returns an std::optional with a some-value, so the compiler can deduce the template parameter/wrapped type (in this example: int32_t) from the type of the supplied wrapped value, meaning you needn't specify it explicitly.

Applied to your example:

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

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



回答2:


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

should do the trick.

The compiler must deduce the result type of the ternary expression from the last two operands, but there is no way it can deduce std::optional<int32_t> from int32_t and {}.

int32_t and std::optional<int32_t> on the other hand do have the desired common type std::optional<int32_t>.


Related fun fact: You can avoid repeating the type with auto return type deduction:

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

Depending on preference, you can of course also infer the template argument for the std::optional from it->second with decltype to further reduce repetition.



来源:https://stackoverflow.com/questions/45389872/return-optional-value-with-operator

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!