5

考虑以下示例:

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.3with上编译得很好-std=c++11。可能是早期 GCC C++11 实现中的一个错误?

断言:

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

问题:

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

1 回答 1

4

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

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

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

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


首先,~t操作数属于类类型,上述异常不适用。

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

于 2014-12-03T21:41:02.817 回答