调用重载运算符时,用户定义的枚举类隐式转换失败

时间:2014-12-03 20:58:10

标签: c++ c++11 operator-overloading implicit-conversion enum-class

考虑以下示例:

struct ConvertibleStruct {};

enum class ConvertibleEC {};

struct Target {
    // Implicit conversion constructors
    Target(ConvertibleStruct) {}
    Target(ConvertibleEC) {}
};

Target operator~(const Target& t) {
    return t;
}

Target anotherFunction(const Target& t) {
    return t;
}

int main() {
    ConvertibleStruct t;
    ConvertibleEC ec;

    ~t;                   // 1. Works finding the operator overloaded above
    ~ec;                  // 2. Fails to compile on clang 3.4 and gcc 4.8.2
    operator~(ec);        // 3. Works finding the operator overloaded above

    anotherFunction(ec);  // 4. Works
}

编译器版本:

以上调查结果适用于clang 3.4gcc 4.8.2。测试2.实际上使用gcc 4.7.3-std=c++11上编译正常。可能是早期GCC C ++ 11实现中的一个错误?

断言:

  • 鉴于1.编译,在调用~运算符时会检查用户定义的隐式转换。
  • 鉴于4.编译,检查用户定义的隐式转换是否为enum class个对象。

问题:

  • 上述断言是否正确?
  • 如果是,为什么2.编译失败?
  • 鉴于2.无法编译,为什么3.编译?

1 个答案:

答案 0 :(得分:4)

第二个测试~ec遇到了表达式中运算符名称查找的特性:[over.match.oper] / 3(来自"古代" N3797):

  

对于一元运算符@,其操作数的类型为cv-nonqualified version T1 [...]

     

非会员候选人的集合是不合格的结果   根据表达式在表达式的上下文中查找operator@   通常的非限定函数调用中的名称查找规则   除了忽略所有成员函数。 但是,如果没有操作数   具有类类型,只有查找集中的非成员函数   具有类型T1的第一个参数或“可能的参考”   cv-qualified)T1“,当T1是枚举类型 [...] 时   候选职能

因此,::operator~(const Target&)不应与for表达式一起使用,并且将一元运算符应用于ConvertibleEC类型的操作数。


对于第一个~t,操作数属于类类型,上述异常不适用。

第三次和第四次测试都不使用运算符查找,而是通常不合格的查找。通常不合格的查找会找到::operator~(const Target&)(在案例1和3中)和anotherFunction(在案例4中)。