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

Cli*_*est 5 c++ operator-overloading implicit-conversion c++11 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
}
Run Code Online (Sandbox Code Playgroud)

编译器版本:

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

断言:

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

问题:

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

dyp*_*dyp 4

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

\n\n
\n

对于操作数@类型为 cv 未限定版本为T1[...] 的一元运算符

\n\n

非成员候选集是operator@根据非限定函数调用中名称查找的常用规则在表达式上下文中进行非限定\n 查找的结果\n,但忽略所有成员函数。但是,如果没有操作数具有类类型,则仅查找集中那些具有第一个参数类型T1或 \xe2\x80\x9c 引用(可能\n cv 限定的)T1\xe2\的非成员函数。 x80\x9d,当T1是枚举类型时[...]是\n 候选函数

\n
\n\n

因此,::operator~(const Target&)不应在 for 表达式中找到/使用 ,该表达式将一元运算符应用于 类型的操作数ConvertibleEC

\n\n
\n\n

对于第一个,~t,操作数是类类型,以上例外情况不适用。

\n\n

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

\n