C++ '?:' 的返回类型(三元条件运算符)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8535226/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Return type of '?:' (ternary conditional operator)
提问by Yola
Why does the first return a reference?
为什么第一个返回一个引用?
int x = 1;
int y = 2;
(x > y ? x : y) = 100;
While the second does not?
而第二个没有?
int x = 1;
long y = 2;
(x > y ? x : y) = 100;
Actually, the second did not compile at all - "not lvalue left of assignment".
实际上,第二个根本没有编译 - “不是赋值的左值”。
采纳答案by CB Bailey
Expressions don't have return types, they have a type and - as it's known in the latest C++ standard - a value category.
表达式没有返回类型,它们有一个类型和——正如在最新的 C++ 标准中所知——一个值类别。
A conditional expression can be an lvalueor an rvalue. This is its value category. (This is somewhat of a simplification, in C++11
we have lvalues, xvalues and prvalues.)
条件表达式可以是左值或右值。这是它的价值类别。(这有点简化,C++11
因为我们有左值、x 值和右值。)
In very broad and simple terms, an lvaluerefers to an object in memory and an rvalueis just a value that may not necessarily be attached to an object in memory.
用非常广泛和简单的术语来说,左值指的是内存中的对象,而右值只是一个不一定附加到内存中对象的值。
An assignment expression assigns a value to an object so the thing being assigned to must be an lvalue.
赋值表达式为对象赋值,因此被赋值的事物必须是左值。
For a conditional expression (?:
) to be an lvalue(again, in broad and simple terms), the second and third operands must be lvaluesof the same type. This is because the type and value category of a conditional expression is determined at compile time and must be appropriate whether or not the condition is true. If one of the operands must be converted to a different type to match the other then the conditional expression cannot be an lvalueas the result of this conversion would not be an lvalue.
对于条件表达式(?:
)是一个左值(再次,在广泛的和简单的术语),所述第二和第三操作数必须是左值的相同类型的。这是因为条件表达式的类型和值类别是在编译时确定的,并且无论条件是否为真,都必须是合适的。如果必须将其中一个操作数转换为不同类型以匹配另一个类型,则条件表达式不能是左值,因为此转换的结果将不是左值。
ISO/IEC 14882:2011 references:
3.10 [basic.lval] Lvalues and rvalues (about value categories)
5.15 [expr.cond] Conditional operator (rules for what type and value category a conditional expression has)
5.17 [expr.ass] Assignment and compound assignment operators (requirement that the l.h.s. of an assignment must be a modifiable lvalue)
ISO/IEC 14882:2011 参考:
3.10 [basic.lval] Lvalues 和 rvalues(关于值类别)
5.15 [expr.cond] 条件运算符(条件表达式具有什么类型和值类别的规则)
5.17 [expr.ass] 赋值和复合赋值运算符(要求赋值的 lhs 必须是可修改的左值)
回答by Xeo
The type of the ternary ?:
expression is the common type of its second and third argument. If both types are the same, you get a reference back. If they are convertable to each other, one gets chosen and the other gets converted (promoted in this case). Since you can't return an lvalue reference to a temporary (the converted / promoted variable), its type is a value type.
三元?:
表达式的类型是其第二个和第三个参数的公共类型。如果两种类型相同,您会得到一个参考。如果它们可以相互转换,一个被选中,另一个被转换(在这种情况下被提升)。由于您无法返回对临时变量(已转换/提升的变量)的左值引用,因此其类型是值类型。
回答by Filip Roséen - refp
It cannot return a lvaluesince it will have to implicitly promote the type of x
to match the type of y
(since both sides of :
are not of the same type), and with that it has to create a temporary.
它不能返回左值,因为它必须隐式提升 of 的类型x
以匹配of的类型y
(因为 的两侧:
不是同一类型),并且它必须创建一个临时的。
What does the standard say? (n1905)
标准怎么说?( n1905)
Expressions 5.17 Assignment and compound assignment operators
表达式 5.17 赋值和复合赋值运算符
5.17/3
If the second and third operand have different types, and either has (possibly cv-qualified) class type, an attempt is made to convert each of those operands to the type of the other. The process for determining whether an operand expression E1 of type T1 can be converted to match an operand expression E2 of type T2 is defined as follows:
— If E2 is an lvalue: E1 can be converted to match E2 if E1 can be implicitly converted (clause 4) to the type “reference to T2”, subject to the constraint that in the conversion the reference must bind directly (8.5.3) to E1.
— If E2 is an rvalue, or if the conversion above cannot be done:
— if E1 and E2 have class type, and the underlying class types are the same or one is a base class of the other: E1 can be converted to match E2 if the class of T2 is the same type as, or a base class of, the class of T1, and the cv-qualification of T2 is the same cv-qualification as, or a greater cv-qualification than, the cv-qualification of T1. If the conversion is applied, E1 is changed to an rvalue of type T2 that still refers to the original source class object (or the appropriate subobject thereof). [Note: that is, no copy is made. — end note] by copy-initializing a temporary of type T2 from E1 and using that temporary as the converted operand.
Otherwise (i.e., if
E1
or E2 has a non class type, or if they both have class types but the underlying classes are not either the same or one a base class of the other): E1 can be converted to match E2 if E1 can be implicitly converted to the type that expression E2 would have if E2 were converted to an rvalue (or the type it has, if E2 is an rvalue).Using this process, It is determined whether the second operand can be converted to match the third operand, and whether the third operand can be converted to match the second operand. If both can be converted, or one can be converted but the conversion is ambiguous, the program is ill-formed. If neither can be converted, the operands are left unchanged and further checking is performed as described below. If exactly one conversion is possible, that conversion is applied to the chosen operand and the converted operand is used in place of the original operand for the remainder of this section.
5.17/3
如果第二个和第三个操作数具有不同的类型,并且其中一个具有(可能是 cv 限定的)类类型,则会尝试将这些操作数中的每一个转换为另一个的类型。确定 T1 类型的操作数表达式 E1 是否可以转换为匹配 T2 类型的操作数表达式 E2 的过程定义如下:
— 如果 E2 是左值:如果 E1 可以隐式转换(第 4 节)到类型“对 T2 的引用”,则可以将 E1 转换为匹配 E2,受制于在转换中引用必须直接绑定的约束(8.5.3 ) 到 E1。
— 如果 E2 是右值,或者无法进行上述转换:
— 如果 E1 和 E2 具有类类型,并且底层类类型相同或一个是另一个的基类:如果 T2 的类与 E1 的类型相同,或者是另一个的基类,则可以将 E1 转换为匹配 E2 ,T1 的类,并且 T2 的 cv 限定与 T1 的 cv 限定相同或更大的 cv 限定。如果应用了转换,则 E1 将更改为 T2 类型的右值,该右值仍引用原始源类对象(或其适当的子对象)。[注:即不复制。— end note] 通过从 E1 复制初始化 T2 类型的临时对象并将该临时对象用作转换后的操作数。
否则(即,如果
E1
或 E2 具有非类类型,或者如果它们都具有类类型但基础类不相同或其中一个是另一个的基类):如果 E1 可以是,则可以将 E1 转换为匹配 E2如果 E2 被转换为右值,则隐式转换为表达式 E2 将具有的类型(或它具有的类型,如果 E2 是右值)。使用这个过程,确定是否可以转换第二个操作数以匹配第三个操作数,以及是否可以转换第三个操作数以匹配第二个操作数。如果两者都可以转换,或者一个可以转换但转换不明确,则程序格式错误。如果两者都不能转换,则操作数保持不变,并按如下所述执行进一步检查。如果恰好可以进行一次转换,则该转换将应用于所选操作数,并在本节的其余部分中使用转换后的操作数代替原始操作数。
5.17/4
If the second and third operands are lvalues and have the same type, the result is of that type and is an lvalue and it is a bit-field if the second or the third operand is a bit-field, or if both are bit-fields.
5.17/4
如果第二个和第三个操作数是左值并且具有相同的类型,则结果属于该类型并且是左值,如果第二个或第三个操作数是位域,或者两者都是位域,则结果是位域领域。
5.17/5
Otherwise, the result is an rvalue. If the second and third operands do not have the same type, and either has (possibly cv-qualified) class type, overload resolution is used to determine the conversions (if any) to be applied to the operands (13.3.1.2, 13.6). If the overload resolution fails, the program is ill-formed. Otherwise, the conversions thus determined are applied, and the converted operands are used in place of the original operands for the remainder of this section.
5.17/5
否则,结果是一个右值。如果第二个和第三个操作数没有相同的类型,并且有一个(可能是 cv 限定的)类类型,则使用重载决议来确定要应用于操作数的转换(如果有)(13.3.1.2、13.6) . 如果重载决议失败,则程序格式错误。否则,将应用如此确定的转换,并且在本节的其余部分中使用转换后的操作数代替原始操作数。