问题 调用转换运算符


以下行为的原因是什么?

class BoolWrapper
{
public:
    BoolWrapper(bool value) : value(value) {}

    operator bool() const { return value; }
    operator int() const { return (int) value; }

private:
    bool value;
};


BoolWrapper bw(true);

if (bw) { ... }            // invokes operator bool()
if (bw == true) { ... }    // invokes operator int() -- why?

这种行为有望吗? (使用GCC 4.7.2。)


6059
2017-11-06 16:05


起源

如果我不得不猜测我会在内置环境中说“整体促销” ==... - Kerrek SB
因此,您应该明确定义 bool operator==(bool); - andre
@ahenderson这将是非法的。用户定义的运算符必须至少使用一个用户定义类型的参数。 - Gorpik
@Gorpik这听起来不对。我指的是运算符作为成员函数。您是将运营商称为全球职能部门吗?这里有一个 链接 它显示了外部和内部类定义。 - andre
@ahenderson对不起,我没注意到你的 operator== 收到一个参数,因此是一个成员函数。在这种情况下,你是对的。 - Gorpik


答案:


您的期望是基于您的信念,即语言已经知道如何比较两个 bool 值。实际上,它听起来并不令人惊讶。更准确地说,语言“不知道”如何做到这一点

在概念层面,C ++没有专门的内置等式比较运算符 bool vs. bool 比较。即使你写作 true == false 在你的代码中,它实际上被语言解释为 (int) true == (int) false。隐式转换为 int 是由规则引入的 通常的算术转换 和 int vs. int 然后使用比较。

最直接的内置运算符,可以比较两个 bool 值是一个 int vs. int 比较。这是编译器在您的情况下尝试使用的运算符。将使用相同的运算符 char vs. char 和 short vs. short 比较。

换句话说,编译器可以使用你的唯一方法 bool 中的转换运算符 bw == true 表达将是做的

(int)(bool) bw == (int) true

这肯定不如直接“最优”

(int) bw == (int) true

这是驱动语言选择后一种变体的逻辑。


6
2017-11-06 16:33



我没有看到符合标准的编译器如何推广 short 至 unsigned int。至于 char,只有它是无符号和大小的 int 是一个字节(确实很奇怪)。 - Gorpik
是的,我在考虑 unsigned 这些类型的版本。我删除了关于异域平台的误导性评论。 - AnT
该 编译器 可能不知道如何比较除了之外的任何东西 int,但是 优化 经常这样做。了解差异很有用。 - Mark Ransom
@Mark Ransom:当我说“由语言解释”时,这正是我试图表达的意思。 “通过语言”旨在与“概念上”,“通过抽象C ++机器”同义。当然,在生成的物理机器代码中转换为 int 完全没必要。我甚至不称之为“优化”。 - AnT
那时来自我的+1。在这种特定情况下,编译器必须选择 int 用户定义的转换,以避免不符合,无论优化或任何事情。 - Gorpik


从5/9开始:

许多二进制运算符,它们期望算术运算或运算   枚举类型导致转换并产生类似的结果类型   办法。目的是产生一种普通类型,它也是一种类型   结果。这种模式称为通常的算术转换,   其定义如下:

[一些无关紧要的浮点项目。]

否则,应对两者进行整体促销(4.5)   操作数。

从3.9.1 / 6我们看到bool有资格进行整体推广:

bool类型的值为true或false.42)[注意:没有   signed,unsigned,short或long bool类型或值。 ]如上所述   在下面,bool值表现为整数类型。 bool类型的值   参加整体促销活动(4.5)。


6
2017-11-06 16:12



很好的回答,谢谢。但是接受了安德烈的回答 (int)(bool) bw == (int) true 例。 - peter.slizik


在第一种情况下,一个 if 条款期望a bool 条件,所以这是选定的转换。

在第二种情况下,您要求在a之间进行比较 BoolWrapper 和a bool。从没有 operator == 如果存在重载,编译器必须将这些参数转换为合适的参数。根据标准(第4.5节, 整体促销),转换的首选整数类型是 int。既然都是 BoolWrapper 和 bool 可以转换为 int,这是选定的转换。


4
2017-11-06 16:13



我完全不遵循这个逻辑。那么如果 BoolWrapper 和 bool可以转换为int吗? BoolWrapper 和 bool 可以转换为(或留下) bool 太。为什么通过bool转换选择整数转换(需要双方转换),只需要一方转换? - David
@Dave请参阅我的答案,标准要求对两个参数都要进行积分促销 ==。 - Mark B
@Dave:可能有人认为只进行一次转换更有意义(BoolWrapper 至 bool,在这种情况下)而不是两个。但是标准对此有最终决定权,它要求将两个值都转换为 int 如果可以的话。 - Gorpik
@Dave,标准不区分a的情况 bool 转换是有道理的,比如 == 以及不是这样的情况 +。如果您正在应用任何算术运算符,它将选择 int。 - Mark Ransom