代码之家  ›  专栏  ›  技术社区  ›  Shahbaz Martin York

三元运算符对int和float的结果`

  •  10
  • Shahbaz Martin York  · 技术社区  · 8 年前

    简而言之,我有以下代码:

    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类型( 浮动 )。后来的标准说,如果转换可以通过两种方式进行,那么程序的格式就不正确。

    这里的规则是什么?我是否处于未定义行为的领域?还是我所看到的转换的标准?

    1 回复  |  直到 8 年前
        1
  •  11
  •   T.C. Yksisarvinen    8 年前

    bool ? int : float 是一个浮点数。

    bool ? int : some_type_convertible_to_float 不是:第三个操作数可以转换为 int (通过将第一个转换为 float 然后到 内景 );这个 内景 (可能)无法转换为 some_type_convertible_to_float 。所以根据你引用的规则,你可以 内景 。