返回types'?:'(三元条件运算符)

为什么第一个返回一个引用?

int x = 1; int y = 2; (x > y ? x : y) = 100; 

而第二个不?

 int x = 1; long y = 2; (x > y ? x : y) = 100; 

实际上,第二个根本没有编译 – “左派不是左派”。

expression式没有返回types,它们有一个types,就像它在最新的C ++标准中已知的那样 – 是一个值类别。

条件expression式可以是左值右值 。 这是它的价值类别。 (这有点简单,在C++11我们有左值,左值和右值)。

在非常宽泛和简单的术语中, 左值指的是内存中的对象,而右值只是一个值,不一定会附加到内存中的对象。

赋值expression式将一个值赋给一个对象,所以被赋值的对象必须是一个左值

对于条件expression式( ?: :)是一个左值 (同样,宽泛而简单), 第二个和第三个操作数必须是相同types左值 。 这是因为条件expression式的types和值类别是在编译时确定的,无论条件是否为真都必须适当。 如果其中一个操作数必须转换为不同的types以匹配另一个,则该条件expression式不能是左值,因为该转换的结果不会是左值

ISO / IEC 14882:2011参考文献:

3.10 [basic.lval]左值和右值(关于值类别)

5.15 [expr.cond]条件运算符(条件expression式具有的types和值类别的规则)

5.17 [expr.ass]赋值和复合赋值运算符(要求赋值的lhs必须是可修改的左值)

三元?:expression式的types是其第二个和第三个参数的常见types。 如果两种types都相同,则返回参考。 如果他们可以相互转换,一个被选中,另一个被转换(在这种情况下被提升)。 由于不能将左值引用返回到临时(转换/升级的variables),因此其types是值types。

它不能返回左值,因为它必须隐含地提升x的types以匹配y的types(因为:两边都不是相同的types),并且必须创build一个临时的。


标准说什么? ( n1905 )

expression式5.17赋值和复合赋值操作符

5.17 / 3

如果第二个和第三个操作数具有不同的types,并且具有(可能是cv-qualified)类types,则尝试将每个操作数转换为另一个的types。 用于确定typesT1的操作数expression式E1是否可以被转换以匹配typesT2的操作数expression式E2的过程定义如下:

– 如果E2是一个左值:如果E1可以被隐式转换(第4章)为types“T2的引用”,则E1可以被转换为与E2匹配,受限于在转换中引用必须直接绑定(8.5.3 )到E1。

– 如果E2是一个右值,或者上面的转换不能完成:

– 如果E1和E2具有types,并且底层types相同或者一个是另一个的基类:如果T2的类是相同types的,则E1可以被转换为匹配E2,或者,T1的等级和T2的cv资格与T1的cv资格相同,或者更高的cv资格。 如果应用转换,则E1被改变为仍然引用原始源类对象(或其适当的子对象)的typesT2的右值。 [ 注:也就是说,没有复制。 – 结束注释 ]通过从E1复制初始化T2types的临时数据并将其作为转换后的操作数使用。

否则(即,如果E1或E2具有非类types,或者它们都具有类types,但是基类不是相同的或者是另一类的基类):如果E1可以将E1转换为匹配E2如果E2被转换成一个右值(或者它所具有的types,如果E2是一个右值),则隐式地转换为expression式E2所具有的types。

使用该过程,确定是否可以将第二操作数转换为与第三操作数相匹配,以及是否可以转换第三操作数以匹配第二操作数。 如果两者都可以转换,或者可以转换,但是转换不明确,那么该程序是不合格的。 如果两者都不能转换,则操作数保持不变,并按照下面的描述进行进一步的检查。 如果只有一次转换是可能的,则该转换将应用于所选的操作数,转换后的操作数将用于本节其余部分的原始操作数。


5.17 / 4

如果第二和第三操作数是左值并且具有相同的types,则结果是该types的,并且是左值,如果第二或第三操作数是位域,或者如果两者都是位值,领域。


5.17 / 5

否则,结果是一个右值。 如果第二个和第三个操作数不具有相同的types,并且具有(可能是cv-qualified)类types,则使用重载决策来确定要应用于操作数的转换(如果有的话)(13.3.1.2,13.6) 。 如果重载parsing失败,则程序不合格。 否则,应用这样确定的转换,并使用转换的操作数代替本节其余部分的原始操作数。