调用重载运算符时,枚举类的用户定义隐式转换失败 [英] User-defined implicit conversion of an enum class when calling an overloaded operator fails

查看:176
本文介绍了调用重载运算符时,枚举类的用户定义隐式转换失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请考虑以下示例:

  struct ConvertibleStruct {}; 

枚举类ConvertibleEC {};

struct Target {
//隐式转换构造函数
Target(ConvertibleStruct){}
Target(ConvertibleEC){}
};

目标运算符〜(const Target& t){
return t;
}

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

int main(){
ConvertibleStruct t;
ConvertibleEC ec;

〜t; // 1.找到操作符重载的
〜ec; // 2.无法在clang 3.4和gcc 4.8.2上编译
operator〜(ec); // 3.找到操作符重载的

anotherFunction(ec); // 4. Works
}

编译器版本: / p>

上述结果适用于 clang 3.4 gcc 4.8.2 。测试2.实际上用 -std = c ++ 11 编译 gcc 4.7.3 上的罚款。可能是早期GCC C ++ 11实现中的错误?



断言




  • 在编译时,当调用运算符时,将检查用户定义的隐式转换。

  • 鉴于4.编译,会检查枚举类对象的用户定义的隐式转换。



问题:





  • 如果是,为什么2.编译失败?

  • $ c>遇到表达式中的操作符的名称查找的特殊性:[over.match.oper] / 3(来自古代N3797):


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



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


    :: operator〜(const Target&)不应该被找到/用于一个表达式,并且将一元运算符应用于 ConvertibleEC






    第一个〜t ,操作数是类类型,并且上述异常不适用。



    第三和第四个测试不使用操作符查找,但通常的非限定查找。通常的非限定查找找到 :: operator〜(const Target&)(在情况1和3中)和 anotherFunction 在情况4)。


    Consider the following example:

    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
    }
    

    Compiler versions:

    The above findings are for clang 3.4 and gcc 4.8.2. Test 2. actually compiles fine on gcc 4.7.3 with -std=c++11. Possibly a bug in early GCC C++11 implementation?

    Assertions:

    • Given that 1. compiles, user-defined implicit-conversions are checked when calling the ~ operator.
    • Given that 4. compiles, user-defined implicit-conversions are checked for enum class objects.

    Questions:

    • Are the above assertions correct?
    • If they are, why does 2. fail to compile?
    • Given that 2. fails to compile, why does 3. compile?

    解决方案

    The second test, ~ec runs into a peculiarity of the name lookup for operators in expressions: [over.match.oper]/3 (from the "ancient" N3797):

    For a unary operator @ with an operand of a type whose cv-unqualified version is T1 [...]

    The set of non-member candidates is the result of the unqualified lookup of operator@ in the context of the expression according to the usual rules for name lookup in unqualified function calls except that all member functions are ignored. However, if no operand has a class type, only those non-member functions in the lookup set that have a first parameter of type T1 or "reference to (possibly cv-qualified) T1", when T1 is an enumeration type [...] are candidate functions.

    So the ::operator~(const Target&) should not be found/used with a for an expression with a unary operator applied to an operand of type ConvertibleEC.


    For the first, ~t, the operand is of class type and the above exception does not apply.

    Both the third and the fourth test do not use operator lookup, but usual unqualified lookup. The usual unqualified lookup finds ::operator~(const Target&) (in cases 1 and 3) and anotherFunction (in case 4).

    这篇关于调用重载运算符时,枚举类的用户定义隐式转换失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆