For a unary operator
@
with an operand of type
cv1 T1,
and for a binary operator
@
with a left operand of type
cv1 T1
and a right operand of type
cv2 T2,
four sets of candidate functions, designated
member candidates,
non-member candidates,
built-in candidates,
and
rewritten 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 for
operator@ 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 for
operator@
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 type
T1
or βreference to
cv T1β,
when
T1
is an enumeration type,
or (if there is a right operand) a second parameter of type
T2
or βreference to
cv T2β,
when
T2
is 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 expression
y <=> x.For the
!= operator (
[expr.eq]),
the rewritten candidates
include all non-rewritten candidates
for the expression
x == y
that 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 == x
that 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 o
unless a search for the name operator!= in the scope S
from the instantiation context of the operator expression
finds a function or function template
that would correspond ([basic.scope.scope]) to F
if its name were operator=,
where S is the scope of the class type of o
if 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
.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 @ y
is interpreted as
0 @ (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, and
x @ 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 an
operator->
function, and is not an argument when the
operator->
function is called. When
operator->
returns, the operator
->
is applied to the value returned, with the original second
operand.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]