布尔复合赋值中的隐式转换?

时间:2015-09-20 21:13:58

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

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

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 <=> +,-,&,|...

2 个答案:

答案 0 :(得分:1)

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

  

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

有两个例外:

b &= f;
b <<= f;

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

  

执行通常的算术转换;结果是操作数的按位AND功能。该   operator 仅适用于整数或未范围的枚举操作数

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

  

操作数应为整数或无范围的枚举类型,并执行整体促销。

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

如果你(以及我在这里重命名你的课程):

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

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

  

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

对于其他整数类型,积分转换,来自[conv.integral]:

  

整数类型的prvalue可以转换为另一个整数类型的prvalue。一个没有眼镜的prvalue   枚举类型可以转换为整数类型的prvalue   [...]
  如果目标类型已签名,则该值如果可以在目标类型中表示,则不会更改;   否则,该值是实现定义的。

来自float的浮动积分转换,来自[conv.fpint]:

  

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

答案 1 :(得分:0)

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

  

如果左操作数不是类类型,则表达式被隐式转换(第4节)到左操作数的cv-unqualified类型。

因此,等效的假设运算符应采用bool参数:

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