简而言之,我有以下代码:
float x = cond ? 0 : x_option;
哪里
x_option
是一个
template<float>
,它具有
operator float()
(并且没有其他自动强制转换运算符。请注意此转换后表达式的类型:
bool ? int : float;
我希望这个表达式的结果是
float
:
C11:
如果第二个和第三个操作数都具有算术类型,则结果类型为
由通常的算术转换决定,它们是否应用于这两个操作数,
是结果的类型。
因此,它遵循与示例相同的规则
float + int
。
C++11:
第二个和第三个操作数具有算术或枚举类型;常用的算术转换
执行,将其转换为公共类型,结果为该类型。
同样的规则。
然而
,clang和cl.exe都会生成
vcvttss2si
引导评估第三个参数的路径中的指令,即它们决定
bool ? int : float
是一个
int
,不是
浮动
哦!
公平地说,C++11有一些规则应该在我引用的规则之前应用,老实说,这些规则不是最容易理解的,尽管从我的理解来看,转换为
内景
不可能:
C++11:
否则,如果第二个和第三个操作数具有不同的类型,并且其中一个具有(可能是cv限定的)类类型,或者如果这两个操作数都是相同值类别和相同类型的glvalues(cv限定除外),则会尝试将这些操作数中的每一个转换为另一个操作数的类型。确定T1类型的操作数表达式E1是否可以转换为与T2类型的操作数表达式E2匹配的过程定义如下:
–如果E2是左值:如果E1可以隐式转换(第4条)为类型–T2的左值引用–E1可以转换为与E2匹配,但必须遵守转换中引用必须直接绑定(8.5.3)到左值的约束。
如果E2是xvalue:如果E1可以隐式转换为T2的类型rvalue引用,则可以将E1转换为与E2匹配,但必须遵守引用必须直接绑定的约束。
如果E2是右值,或者上述转换都无法完成,并且至少有一个操作数具有(可能是cv限定的)类类型:
-
如果E1和E2具有类类型,并且基础类类型相同,或者其中一个是另一个的基类:如果T2的类与T1的类相同,或者是T1的基类,并且T2的cv资格与T1的cv资格相同,或者cv资格大于T1的cv资格,则可以将E1转换为与E2匹配。如果应用转换,则通过复制初始化E1中T2类型的临时值并将该临时值用作转换后的操作数,将E1更改为T2类型的prvalue。
-
否则(即,如果E1或E2具有非类类型,或者如果它们都具有类类型,但基础类既不相同,也不是一个基类,而是另一个基类):如果E1可以隐式转换为E2转换为prvalue时表达式E2将具有的类型(或者如果E2是prvalue,则其具有的类型),则E1可以转换为与E2匹配。
使用此过程,可以确定是否可以将第二个操作数转换为与第三个操作数匹配,以及是否可以将第三个操作数转换为与第二个操作数匹配。如果两者都可以转换,或者其中一个可以转换但转换不明确,则程序格式错误。
根据我在上面的理解,这属于第三种情况的第二种情况(最后一个项目符号的最后一个项目符号),因此E1(类型
内景
)应转换为E2类型(
浮动
)。后来的标准说,如果转换可以通过两种方式进行,那么程序的格式就不正确。
这里的规则是什么?我是否处于未定义行为的领域?还是我所看到的转换的标准?