问题
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 typestd::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 withnullopt_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