【问题标题】:Implicit conversions in boolean compound assignment?布尔复合赋值中的隐式转换?
【发布时间】:2015-12-17 12:18:10
【问题描述】:

我想了解以下情况会发生什么:

bool b = false;
float f = 3.14;
char c = 1;
int i = 2;
unsigned int u = 3;
long long int ll = 4;
unsigned long long int ull = 5;

b += f;
b += c;
b += i;
b += u;
b += ll;
b += ull;

b &= f;
b &= c;
b &= i;
b &= u;
b &= ll;
b &= ull;

b <<= f;
b <<= c;
b <<= i;
b <<= u;
b <<= ll;
b <<= ull;

或者换句话说,按照标准进行的隐式转换是什么?

其他问题:如果为假设的bool 类提供的复合赋值的唯一签名是以下形式,那么结果是否相同:

class bool {bool& operator op=(int x) noexcept;}; // op <=> +,-,&,|...

【问题讨论】:

    标签: c++ boolean language-lawyer implicit-conversion


    【解决方案1】:

    所有这些情况下的相关转换都是布尔转换,[conv.bool]:

    算术纯右值、无范围枚举、指针或指向成员类型的指针可以转换为 bool 类型的纯右值。零值、空指针值或空成员指针值转换为false; 任何其他值都将转换为true。对于直接初始化 (8.5),std::nullptr_t 类型的纯右值可以 转换为bool 类型的纯右值;结果值为false

    有两个例外:

    b &= f;
    b <<= f;
    

    前者,因为[expr.bit.and]:

    执行通常的算术转换;结果是操作数的按位与函数。这 运算符仅适用于整数或无范围枚举操作数

    和后者,因为[expr.shift]:

    操作数应为整数或非范围枚举类型,并执行整数提升。

    由于float 既不是整数也不是无作用域枚举类型,所以这两个操作无效。


    对于你的(我在这里重命名你的班级):

    class Bool {Bool& operator op=(int x) noexcept;}; // op <=> +,-,&,|...
    

    我们会根据类型选择三种转换中的一种。对于charbool,我们进行整体促销,[conv.prom]:

    boolchar16_tchar32_twchar_t 之外的整数类型的纯右值,其整数转换 rank (4.13) 小于 int 的 rank 如果int 可以代表所有,则可以转换为 int 类型的prvalue 源类型的值;否则,源纯右值可以转换为 unsigned int 类型的纯右值。
    [...]
    bool 类型的纯右值可以转换为 int 类型的纯右值,false 变为零,true 合而为一。

    对于其他整数类型,Integral Conversion,来自 [conv.integral]:

    整数类型的纯右值可以转换为另一种整数类型的纯右值。无作用域的prvalue 枚举类型可以转换为整数类型的prvalue。
    [...]
    如果目标类型是有符号的,则如果它可以在目标类型中表示,则值不变; 否则,该值是实现定义的。

    对于float,浮点积分转换,来自 [conv.fpint]:

    浮点类型的纯右值可以转换为整数类型的纯右值。转换截断; 也就是说,小数部分被丢弃。如果截断的值不能是未定义的行为 以目标类型表示。

    【讨论】:

      【解决方案2】:

      对于复合赋值表达式,首先将右操作数转换为左操作数的类型(C++14 5.17 p3):

      如果左操作数不是类类型,则表达式被隐式转换(第 4 条)为左操作数的 cv 非限定类型。

      正因为如此,等效的假设运算符应该带一个布尔参数:

      class bool {bool& operator op=(bool x) noexcept;};
      

      下面是一个例子,如果你改用int 会有所不同:

      #include <iostream>
      
      struct Bool {
        bool value;
      
        Bool(bool value) : value(value) { }
        Bool &operator += (int x) noexcept { value += x; return *this; }
      };
      
      int main()
      {
        Bool fake_bool = false;
        bool real_bool = false;
      
        fake_bool += 0.1;
        real_bool += 0.1;
        std::cout << fake_bool.value << "\n";
        std::cout << real_bool << "\n";
      }
      

      输出

      0
      1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-04-11
        • 2010-11-16
        • 1970-01-01
        • 1970-01-01
        • 2018-01-03
        • 2017-02-17
        • 1970-01-01
        相关资源
        最近更新 更多