Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lifetime extension and the conditional operator

Tags:

local lvalue references-to-const and rvalue references can extend the lifetime of temporaries:

const std::string& a = std::string("hello");
std::string&& b = std::string("world");

Does that also work when the initializer is not a simple expression, but uses the conditional operator?

std::string&& c = condition ? std::string("hello") : std::string("world");

What if one of the results is a temporary object, but the other one isn't?

std::string d = "hello";
const std::string& e = condition ? d : std::string("world");

Does C++ mandate the lifetime of the temporary be extended when the condition is false?

The question came up while answering this question about non-copyable objects.

like image 456
fredoverflow Avatar asked Jan 18 '13 19:01

fredoverflow


People also ask

What is the conditional operator in Verilog?

SystemVerilog. The conditional operator ?: chooses, based on a first expression, between a second and third expression. The first expression is called the condition. If the condition is 1, the operator chooses the second expression.

Which are the conditional operators?

There are three conditional operators: && the logical AND operator. || the logical OR operator. ?: the ternary operator.

What is the conditional expression operator?

The conditional operator (? :) is a ternary operator (it takes three operands). The conditional operator works as follows: The first operand is implicitly converted to bool . It is evaluated and all side effects are completed before continuing.

What is conditional operator and its syntax?

The conditional (ternary) operator is the only JavaScript operator that takes three operands: a condition followed by a question mark ( ? ), then an expression to execute if the condition is truthy followed by a colon ( : ), and finally the expression to execute if the condition is falsy.


2 Answers

Both of those are fine.

§5.16 says (extraordinarily abridged):

2 If either the second or the third operand has type void

Nope.

3 Otherwise, if the second and third operand have different types

Nope.

4 If the second and third operands are glvalues of the same value category

Nope. (In the first, both are prvalues and in the second one is a glvalue and one is a prvalue.)

5 Otherwise, the result is a prvalue

Okay, so both of these result in prvalues. So the binding is fine, but what's the binding to?

6 Lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are per- formed on the second and third operands.

Okay, so both are now rvalues if they weren't already.

6 (continued) After those conversions, one of the following shall hold:

The second and third operands have the same type; the result is of that type. If the operands have class type, the result is a prvalue temporary of the result type, which is copy-initialized from either the second operand or the third operand depending on the value of the first operand.

Okay, so it's either std::string(first_operand) or std::string(second_operand).

Regardless, the result of the conditional expression is a new prvalue temporary, and it's that value that's extended by binding to your references.

like image 130
GManNickG Avatar answered Oct 13 '22 12:10

GManNickG


std::string d = "hello";
const std::string& e = condition ? d : std::string("world");

Does C++ mandate the lifetime of the temporary be extended when the condition is false?

It will be. The conditional is an rvalue expression, and when bound with a const reference the compiler will create an unnamed object and bind the reference to it. What I am not 100% sure is whether the temporary whose lifetime is extended is std::string("world") or whether a copy of it is (conceptually) made (and elided).

like image 44
David Rodríguez - dribeas Avatar answered Oct 13 '22 14:10

David Rodríguez - dribeas