问题
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?
回答1:
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 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).
来源:https://stackoverflow.com/questions/27281500/user-defined-implicit-conversion-of-an-enum-class-when-calling-an-overloaded-ope