Here is what I want to achieve:
struct A { A(/* ... */) {} A(A const&) = delete; };
struct B { B(/* ... */) {} B(B const&) = delete; };
int main()
{
static bool constexpr cond = false;
[[maybe_unused]]
A a(/* ... */);
[[maybe_unused]]
B b(/* ... */);
std::conditional_t<cond, A, B> c = cond ? a : b;
return 0;
}
This doesn't compile, since the "?" operator requires both types to be convertible to each other. What I (obviously) need is that c
is a
or b
depending on wheter cond
is true
or false
. How can I achieve that?
Something which technically works, but isn't very pretty:
auto& c = [&] -> auto& {
if constexpr (cond) return a;
else return b;
}();
// rest of function ...
This relies on if constexpr
being able to influence the deduced return type of this lambda expression.
Therefore, it also relies on cond
being a constant expression.
However, it is pretty rare that you would have to do this.
Usually, you would write a function template which works with either A
or B
and then pass in the appropriate object.
// f could also be a separate function
auto f = [&](auto& c) {
// rest of function ...
};
// this uses "if constexpr", but would work with a regular if statement too
if constexpr (cond) f(a);
else f(b);