Jan. 9, 2010, 11:44 a.m.
posted by nogood
Item 26. Operator Function LookupSometimes it looks like a member operator function overloads a non-member operator, but this is not the case. It's not overloading; it's just a different lookup algorithm. Consider the following class that overloads an operator as a member function:
class X {
public:
X operator %( const X & ) const; // binary modulus
X memFunc1( const X & );
void memFunc2();
//...
};
We can call an overloaded operator function with either infix or function call syntax: X a, b, c; a = b % c; // infix call to member operator % a = b.operator %( c ); // member function call a = b.memFunc1( c ); // another member function call When we use the function call syntax, the usual lookup rules apply (see Member Function Lookup [24, 87]), and the call b.operator %(c) is treated in the same way as the similar call to memFunc1. However, an infix call of an overloaded operator is handled differently:
X operator %( const X &, int ); // non-member operator
//...
void X::memFunc2() {
*this % 12; // calls non-member operator %
operator %( *this, 12 ); // error! too many arguments
}
For an infix operator call, the compiler will consider both member and non-member functions (see also Argument Dependent Lookup [25, 89]), so the first, infix call to operator % will match the non-member. This is not an instance of overloading; it's a question of the compiler looking in two different places for candidate functions. The second, non-infix call of operator % follows the standard function lookup rules and finds the member function. We have an error because we are attempting to pass three arguments to a binary function. (Remember the implicit this argument for member functions!) In effect, infix calls of overloaded operators implement a kind of "degenerate" ADL in which both the class of the left (or only) argument of the infix operator and the global scope are considered when determining what functions will be considered for overload resolution. ADL extends this process to include candidate operator functions in other namespaces brought in by the arguments of the operator. Note that this is not overloading. Overloading is a static property of a function declaration (see Overloading and Overriding Are Different [21, 75]). Both ADL and infix operator function lookup are properties of the arguments supplied to a function call. |
- Comment