【问题标题】:Implicit type conversions - Compiler error隐式类型转换 - 编译器错误
【发布时间】:2010-08-20 09:31:44
【问题描述】:

此问题与this 问题有关。下面的代码可以很好地编译 VC9 编译器,但是在使用 Comeau 在线编译时会报错。谁能告诉我哪个是正确的,错误的含义是什么?

错误:模棱两可的“?”操作:第二 “TypesafeBool”类型的操作数可以是 转换为第三个操作数类型 "bool",反之亦然 TypesafeBool b = (1==1) ? f() : 错误;

class TypesafeBool
{
private:
    bool m_bValue;
    struct Bool_ { 
        int m_nValue; 
    };
    typedef int Bool_::* bool_;
    inline bool_ True() const { return &Bool_::m_nValue; }
    inline bool_ False() const { return 0; }

public:
    TypesafeBool( const bool bValue ) : m_bValue( bValue ){}
    operator bool_() const { return m_bValue ? True() : False(); }
};

TypesafeBool f()
{
    return TypesafeBool(true);
}

int main()
{
    TypesafeBool b = (1==1) ? f() : false;
}

【问题讨论】:

  • 我认为 Comeau 在这种情况下是正确的。甚至 g++ 和 Clang++ 也会给出同样的错误。我在 g++ 的情况下得到的错误是 error: operands to ?: have different types 'TypesafeBool' and 'bool
  • 应该明确构造函数的好例子之一

标签: c++ compiler-errors type-conversion


【解决方案1】:

错误是三元运算符必须只有一个类型,而您的表达式(1=1) ? f() : false 有两种类型——f()TypesafeBool 类型,falsebool 类型。您可以在它们之间进行转换,但 Comeau 不知道您要使用哪个。要解决它,请将三元组的一侧转换为另一侧的类型:(1=1) ? f() : TypesafeBool(false)

Comeau 在这里是正确的,因为对于观察者来说结果应该采用什么类型是显而易见的,但三元表达式需要有自己的单一类型,而不参考它的用途,它应该选择的类型是模棱两可。

【讨论】:

  • 很好的答案。因此,您可以转换导致问题的两种方式。真是太遗憾了,因为我想要的是替换bool,它会为我做额外的检查。不过,我不能到处乱扔代码。
  • 第 5.16/3 节非常详细地讨论了规则:)
  • @jkp:在某些情况下,您可以限制其中一种转换——在这种情况下,它必须是隐式的bool->TypesafeBool 转换以避免歧义。
【解决方案2】:

操作员的两种情况?结果必须具有相同的类型。它们的自然类型是 TypesafeBool 和 bool。由于存在从 bool 到 TypesafeBool 以及从 bool 到 TypesafeBool 的隐式转换,因此应该应用歧义。

C++ 规则阻止了结果随后在预期 TypesafeBool 的上下文中使用的事实或已知结果被考虑以倾向于第二种方式的事实

TypesafeBool b = (1 == 1)? f() : TypesafeBool(false);

应该可以。

【讨论】:

    【解决方案3】:

    继@hype 的评论之后,this article 也提出了相同的想法,但构造函数标记为explicit。这消除了您的歧义。

    请注意,如果您将 b 的初始化更改为

    ,您的示例将可以正常工作
    TypesafeBool b( (1==1) ? f() : false );
    

    因为= 语法在标记为显式时不允许调用TypesafeBool( bool )(因为它在技术上是两个构造函数的组合)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-10
      • 1970-01-01
      • 2014-05-28
      • 2014-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-12
      相关资源
      最近更新 更多