[over.match.oper] (original) (raw)
12 Overloading [over]
12.2 Overload resolution [over.match]
12.2.2 Candidate functions and argument lists [over.match.funcs]
12.2.2.3 Operators in expressions [over.match.oper]
If no operand of an operator in an expression has a type that is a class or an enumeration, the operator is assumed to be a built-in operator and interpreted according to [expr.compound].
[Note 1:
Because.,.*, and::cannot be overloaded, these operators are always built-in operators interpreted according to[expr.compound].
?:cannot be overloaded, but the rules in this subclause are used to determine the conversions to be applied to the second and third operands when they have class or enumeration type ([expr.cond]).
— _end note_]
[Example 1: struct String { String (const String&); String (const char*);operator const char* ();}; String operator + (const String&, const String&);void f() { const char* p= "one" + "two"; int I = 1 + 1; } — _end example_]
If either operand has a type that is a class or an enumeration, a user-defined operator function can be declared that implements this operator or a user-defined conversion can be necessary to convert the operand to a type that is appropriate for a built-in operator.
In this case, overload resolution is used to determine which operator function or built-in operator is to be invoked to implement the operator.
Therefore, the operator notation is first transformed to the equivalent function-call notation as summarized in Table 18(where @ denotes one of the operators covered in the specified subclause).
However, the operands are sequenced in the order prescribed for the built-in operator ([expr.compound]).
For a unary operator @with an operand of type cv1 T1, and for a binary operator @with a left operand of type cv1 T1and a right operand of type cv2 T2, four sets of candidate functions, designatedmember candidates,non-member candidates,built-in candidates, andrewritten candidates, are constructed as follows:
- If T1 is a complete class type or a class currently being defined, the set of member candidates is the result of a search foroperator@ in the scope of T1; otherwise, the set of member candidates is empty.
- For the operators =, [], or ->, the set of non-member candidates is empty; otherwise, it includes the result of unqualified lookup foroperator@in the rewritten function call ([basic.lookup.unqual], [basic.lookup.argdep]), ignoring all member functions.
However, if no operand has a class type, only those non-member functions in the lookup set that have a first parameter of typeT1or “reference to cv T1”, whenT1is an enumeration type, or (if there is a right operand) a second parameter of typeT2or “reference to cv T2”, whenT2is an enumeration type, are candidate functions. - For the operator,, the unary operator&, or the operator->, the built-in candidates set is empty.
For all other operators, the built-in candidates include all of the candidate operator functions defined in [over.built] that, compared to the given operator,- have the same operator name, and
- accept the same number of operands, and
- accept operand types to which the given operand or operands can be converted according to [over.best.ics], and
- do not have the same parameter-type-list as any non-member candidate or rewritten non-member candidate that is not a function template specialization.
- The rewritten candidate set is determined as follows:
- For the relational ([expr.rel]) operators, the rewritten candidates include all non-rewritten candidates for the expression x <=> y.
- For the relational ([expr.rel]) and three-way comparison ([expr.spaceship]) operators, the rewritten candidates also include a synthesized candidate, with the order of the two parameters reversed, for each non-rewritten candidate for the expressiony <=> x.
- For the != operator ([expr.eq]), the rewritten candidates include all non-rewritten candidates for the expression x == ythat are rewrite targets with first operand x (see below).
- For the equality operators, the rewritten candidates also include a synthesized candidate, with the order of the two parameters reversed, for each non-rewritten candidate for the expression y == xthat is a rewrite target with first operand y.
- For all other operators, the rewritten candidate set is empty.
[Note 2:
A candidate synthesized from a member candidate has its object parameter as the second parameter, thus implicit conversions are considered for the first, but not for the second, parameter.
— _end note_]
A non-template function or function template F named operator==is a rewrite target with first operand ounless a search for the name operator!= in the scope Sfrom the instantiation context of the operator expression finds a function or function template that would correspond ([basic.scope.scope]) to Fif its name were operator==, where S is the scope of the class type of oif F is a class member, and the namespace scope of which F is a member otherwise.
A function template specialization named operator== is a rewrite target if its function template is a rewrite target.
[Example 2: struct A {};template<typename T> bool operator==(A, T); bool a1 = 0 == A(); template<typename T> bool operator!=(A, T);bool a2 = 0 == A(); struct B { bool operator==(const B&); };struct C : B { C(); C(B);bool operator!=(const B&); };bool c1 = B() == C(); bool c2 = C() == B(); struct D {};template<typename T> bool operator==(D, T); inline namespace N { template<typename T> bool operator!=(D, T); } bool d1 = 0 == D(); — _end example_]
For the first parameter of the built-in assignment operators, only standard conversion sequences ([over.ics.scs]) are considered.
For all other operators, no such restrictions apply.
The set of candidate functions for overload resolution for some operator @is the union of the member candidates, the non-member candidates, the built-in candidates, and the rewritten candidates for that operator @.
The argument list contains all of the operands of the operator.
[Example 3: struct A { operator int();}; A operator+(const A&, const A&);void m() { A a, b; a + b; } — _end example_]
If a rewritten operator<=> candidate is selected by overload resolution for an operator @,x @ yis interpreted as0 @ (y <=> x)if the selected candidate is a synthesized candidate with reversed order of parameters, or (x <=> y) @ 0 otherwise, using the selected rewritten operator<=> candidate.
Rewritten candidates for the operator @are not considered in the context of the resulting expression.
If a rewritten operator== candidate is selected by overload resolution for an operator @, its return type shall be cv bool, andx @ y is interpreted as:
- if @ is !=and the selected candidate is a synthesized candidate with reversed order of parameters,!(y == x),
- otherwise, if @ is !=,!(x == y),
- otherwise (when @ is ==),y == x,
in each case using the selected rewritten operator== candidate.
If a built-in candidate is selected by overload resolution, the operands of class type are converted to the types of the corresponding parameters of the selected operation function, except that the second standard conversion sequence of a user-defined conversion sequence is not applied.
Then the operator is treated as the corresponding built-in operator and interpreted according to [expr.compound].
[Example 4: struct X { operator double();};struct Y { operator int*();};int *a = Y() + 100.0; int *b = Y() + X(); — _end example_]
The second operand of operator->is ignored in selecting anoperator->function, and is not an argument when theoperator->function is called.
Whenoperator->returns, the operator->is applied to the value returned, with the original second operand.104
If the operator is the operator,, the unary operator&, or the operator->, and there are no viable functions, then the operator is assumed to be the built-in operator and interpreted according to[expr.compound].
[Note 3:
The lookup rules for operators in expressions are different than the lookup rules for operator function names in a function call, as shown in the following example:struct A { };void operator + (A, A);struct B { void operator + (B);void f ();}; A a;void B::f() { operator+ (a,a); a + a; }
— _end note_]