I want to initialise an std::optional from another std::optional and some additional arguments provided that the latter std::optional is not empty. Unfortunately std::optional::optional 4) and 5) are not suitable as the amount of arguments is different.
I was able to come up with the following, but it still feels excessive. I particularly don't like specifying return type for the lambda explicitly.
Is there an better (as in more succinct and more expressive) way to achieve this?
#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); }
val{ oi ? decltype(val){{*oi, f, c}} : std::nullopt }?decltypeby any chance?flat_mapfunction to go withstd::optional, but I don't think that there's a standard one.std::tuple{*oi, f, c}is probably clearer than thedecltype, though they're not identical.