【问题标题】:Invoking conversion operators调用转换运算符
【发布时间】:2012-10-26 15:11:00
【问题描述】:

以下行为的原因是什么?

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。)

【问题讨论】:

  • 如果我不得不猜测我会在内置 == 的上下文中说“整体促销”...
  • 因此你应该明确定义bool operator==(bool);
  • @ahenderson 那是非法的。用户定义的运算符必须至少有一个用户定义类型的参数。
  • @Gorpik 这听起来不对。我将运算符称为成员函数。您是否将运算符称为全局函数?这是一个link,它显示了外部和内部类定义。
  • @ahenderson 抱歉,我没有注意到您的 operator== 收到一个参数,因此是一个成员函数。在这种情况下你是对的。

标签: c++ operators


【解决方案1】:

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

在概念级别上,C++ 没有专门用于bool vs. bool 比较的内置相等比较运算符。即使你在代码中写了true == false,它实际上也被语言解释为(int) true == (int) false。到int 的隐式转换由普通算术转换的规则引入,之后使用int vs. int 比较。

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

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

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

这肯定不如直接“最佳”

(int) bw == (int) true

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

【讨论】:

  • 我看不出符合标准的编译器如何将short 提升为unsigned int。至于char,只有当它是无符号的并且int 的大小是一个字节(确实很奇怪)。
  • 是的,我在考虑这些类型的unsigned 版本。我删除了有关外来平台的误导性评论。
  • 编译器可能不知道如何比较int以外的任何东西,但优化器通常会。了解区别很有用。
  • @Mark Ransom:当我说“由语言解释”时,这正是我试图传达的意思。 “By the language”意在与“conceptually”、“by abstract C++ machine”同义。当然,在生成的物理机器代码中,转换为int 是完全没有必要的。我什至不会称其为“优化”。
  • 然后从我这里+1。在这种特定情况下,编译器必须选择 int 用户定义的转换以避免不一致,无论优化或任何东西。
【解决方案2】:

从 5 月 9 日开始:

许多二元运算符需要算术或 枚举类型导致转换并产生类似的结果类型 大大地。目的是产生一个通用类型,这也是 结果。这种模式称为通常的算术转换, 定义如下:

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

否则,积分促销 (4.5) 应在两者上执行 操作数。

从 3.9.1/6 开始,我们看到 bool 有资格进行积分提升:

bool 类型的值要么是真要么是假。42) [注意:没有 有符号、无符号、短或长布尔类型或值。 ] 如前所述 下面,布尔值表现为整数类型。 bool 类型的值 参与积分促销 (4.5)。

【讨论】:

  • 很好的答案,谢谢。不过,接受了 Andrey 的回答,用于他的 (int)(bool) bw == (int) true 示例。
【解决方案3】:

在第一种情况下,if 子句需要 bool 条件,因此这是选定的转换。

在第二种情况下,您要求比较 BoolWrapperbool。由于不存在 operator == 重载来执行此操作,因此编译器必须将这些参数转换为合适的参数。根据标准(第 4.5 节,积分促销),转换的首选积分类型是 int。由于BoolWrapperbool 都可以转换为int,因此这是选定的转换。

【讨论】:

  • 我不完全遵循这个逻辑。那么如果BoolWrapperbool可以转换成int呢? BoolWrapperbool 也可以转换为(或保留)bool。为什么选择整数转换(需要双方转换)而不是只需要一侧转换的布尔转换?
  • @Dave 看我的回答,标准要求对== 的两个参数都进行积分提升。
  • @Dave:有人可能会说,只进行一次转换(在本例中为BoolWrapperbool)而不是两次更有意义。但该标准对此有最终决定权,如果可以的话,它要求将这两个值都转换为int
  • @Dave,标准没有区分bool 转换有意义的情况,例如==,和没有意义的情况,例如+。如果您应用任何算术运算符,它将选择int
猜你喜欢
  • 1970-01-01
  • 2012-01-27
  • 2016-11-11
  • 2017-03-29
  • 2020-06-17
  • 2011-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多