Let's suppose we have some non-copyable and non-movable type Foo, and a function
int f(const Foo& foo) {
... // somehow compute the result depending on the value of foo.
}
Now let's suppose we want want to call this function like this:
const Foo foo1{ 42 };
bool condition = getCondition();
int result = f(condition ? foo : Foo{ 150 });
This won't compile because foo and Foo{ 150 } are of different value categories, so, by definition, the ternary operator will return a prvalue of type Foo - which means that foo1 will need to be copied if condition == true, so this causes a compilation error.
However, C++ guarantees that temporary objects remain valid until the end of the expression, so we can instead write this:
const Foo foo1{ 42 };
bool condition = getCondition();
int result = f(condition ? foo1 : static_cast<const Foo&>(Foo{ 150 });
Now the ternary operator returns const Foo&, and even if this reference refers to Foo{ 150 }, this temporary object will remain valid until the end of the expression. No copying/moving takes place, so this compiles.
Obviously, a safer option would be to just write:
int result = condition ? f(foo1) : f(Foo{ 150 });
However, this can lead to a lot of boilerplate if there are additional parameters, and grows exponentially for multiple "conditional" parameters:
int result = condition1
? (condition2 ? f(foo1, foo2) : f(foo1, Foo{ 222 }))
: (condition2 ? f(Foo{ 111 }, foo2) : f(Foo{ 111 }, Foo{ 222 }));
The hack above allows a shorter form:
int result = f( condition1 ? foo1 : static_cast<const Foo&>(Foo{ 111 }),
condition2 ? foo2 : static_cast<const Foo&>(Foo{ 222 }) );
I understand that this is somewhat risk-prone, but am I correct that the code above is valid?
P.S. I also wonder whether the compiler generates O(N) or O(2^N) instructions when there are N such "conditional" parameters.
Ternary operator and prolonging the lifetime of a temporary object via reference-to-const addresses a similar scenario, but the question there is whether the ternary operator itself prolongs the lifetime of a temporary - it doesn't.