Motivation
With C++ having gotten optional's (in C++17), it is now common to want to write the equivalent of:
If a condition holds, initialize my variable with some expression; and if the condition doesn't hold, keep my variable empty/unassigned
How would we write that in C++? Suppose our expression is of type int
. The "ideal", or most convenient, syntax one might hope would work is:
auto myopt = some_condition ? std::nullopt : 123;
but optional is a library type, which the language knows nothing about, so it doesn't have much of a reason to harmonize nullopt_t
with int
into an optional<int>
.
So, let's try being a little more verbose:
std::optional<int> myopt = some_condition ? std::nullopt : 123;
This still fails, as int
can't be converted into nullopt_t
and vice-versa.
We could write this:
auto myopt = some_condition ? std::nullopt : std::optional<int>(123);
which is ok-ish. But we're again in trouble if our type is not a plain integer but something more complex:
struct mystruct { int x; double y; };
/// -snip-
auto myopt = some_condition ? std::nullopt : std::optional<mystruct>{ 12, 3.4 };
... which fails to compile.
so,
Actual question
What is a decent, succinct (DRY...), single-instruction idiom for initializing an optional with either a value or nullopt? Note it must work for more complex types as well.
Note: C++ constructs introduced later than C++17 are also acceptable, but please mention which language version they're from.
std::optional<mystruct>{ 12, 3.4 }
fails to compile,std::optional<mystruct>{{ 12, 3.4 }}
doesn't.std::optional{myclass{}}
. C++20 for sure, but I guess C++17 might also work. The plus side is for copy/move the explicit typname can be removed:std::optional{"yes"s}
must result in astd::optional<std::string>
. However for none-aggregate types this invokes a move construction.