调用重载运算符时,枚举类的用户定义隐式转换失败 [英] User-defined implicit conversion of an enum class when calling an overloaded operator fails
问题描述
请考虑以下示例:
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 $ c $的第一个参数的非成员函数当
[...] 是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
andgcc 4.8.2
. Test 2. actually compiles fine ongcc 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 isT1
[...]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 typeT1
or "reference to (possibly cv-qualified)T1
", whenT1
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 typeConvertibleEC
.
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) andanotherFunction
(in case 4).这篇关于调用重载运算符时,枚举类的用户定义隐式转换失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- Given that 1. compiles, user-defined implicit-conversions are checked when calling the