The candidate operator functions that represent the built-in operators
defined in [expr.compound] are specified in this subclause.

These candidate
functions participate in the operator overload resolution process as
described in [over.match.oper] and are used for no other purpose.

[Note 1: *end note*]

Because built-in operators take only operands with non-class type,
and operator overload resolution occurs only when an operand expression
originally has class or enumeration type,
operator overload resolution can resolve to a built-in operator only
when an operand has a class type that has a user-defined conversion to
a non-class type appropriate for the operator, or when an operand has
an enumeration type that can be converted to a type appropriate
for the operator.

Also note that some of the candidate operator functions given in this subclause are
more permissive than the built-in operators themselves.

As
described in [over.match.oper], after a built-in operator is selected
by overload resolution the expression is subject to the requirements for
the built-in operator given in [expr.compound], and therefore to any
additional semantic constraints given there.

If there is a user-written
candidate with the same name and parameter types as a built-in
candidate operator function, the built-in operator function
is hidden and is not included in the set of candidate functions.

— In this subclause, the term
promoted integral type
is used to refer to those integral types which are preserved by
integral promotion (including e.g.
int
and
long
but excluding e.g.
char).

For every pair
(T,
vq),
where
T
is an arithmetic type other than bool,
there exist candidate operator functions of the form
vq T& operator++(vq T&);
T operator++(vq T&, int);

For every pair
(T,
vq),
where
T
is an arithmetic type other than
bool,
there exist candidate operator functions of the form
vq T& operator--(vq T&);
T operator--(vq T&, int);

For every pair
(T,
vq),
where
T
is a cv-qualified or cv-unqualified object type,
there exist candidate operator functions of the form
T*vq& operator++(T*vq&);
T*vq& operator--(T*vq&);
T* operator++(T*vq&, int);
T* operator--(T*vq&, int);

For every cv-qualified or cv-unqualified object type
T,
there exist candidate operator functions of the form
T& operator*(T*);

For every function type
T that does not have cv-qualifiers or a ref-qualifier,
there exist candidate operator functions of the form
T& operator*(T*);

For every floating-point or promoted integral type T,
there exist candidate operator functions of the form
T operator+(T);
T operator-(T);

For every promoted integral type
T,
there exist candidate operator functions of the form
T operator~(T);

For every quintuple
(C1,
C2,
T,
cv1,
cv2),
where
C2
is a class type,
C1
is the same type as C2 or is a derived class of C2, and
T
is an object type or a function type,
there exist candidate operator functions of the form
cv12 T& operator->*(cv1 C1*, cv2 T C2::*);
where cv12 is the union of cv1 and cv2.

The return type is shown for exposition only; see [expr.mptr.oper] for the
determination of the operator's result type.

For every pair of types L and R,
where each of L and R is a
floating-point or promoted integral type,
there exist candidate operator functions of the form
LR operator*(L, R);
LR operator/(L, R);
LR operator+(L, R);
LR operator-(L, R);
bool operator==(L, R);
bool operator!=(L, R);
bool operator<(L, R);
bool operator>(L, R);
bool operator<=(L, R);
bool operator>=(L, R);
where
LR
is the result of the usual arithmetic conversions ([expr.arith.conv]) between types
L
and
R.

For every integral type T
there exists a candidate operator function of the form
std::strong_ordering operator<=>(T, T);

For every pair of floating-point types
L and R,
there exists a candidate operator function of the form
std::partial_ordering operator<=>(L, R);

For every cv-qualified or cv-unqualified object type
T
there exist candidate operator functions of the form
T* operator+(T*, std::ptrdiff_t);
T& operator[](T*, std::ptrdiff_t);
T* operator-(T*, std::ptrdiff_t);
T* operator+(std::ptrdiff_t, T*);
T& operator[](std::ptrdiff_t, T*);

For every
T,
where
T
is a pointer to object type,
there exist candidate operator functions of the form
std::ptrdiff_t operator-(T, T);

For every T, where T is an enumeration type or a pointer type,
there exist candidate operator functions of the form
bool operator==(T, T);
bool operator!=(T, T);
bool operator<(T, T);
bool operator>(T, T);
bool operator<=(T, T);
bool operator>=(T, T);
R operator<=>(T, T);
where R is the result type specified in [expr.spaceship].

For every T, where T
is a pointer-to-member type or std::nullptr_t,
there exist candidate operator functions of the form
bool operator==(T, T);
bool operator!=(T, T);

For every pair of promoted integral types
L
and
R,
there exist candidate operator functions of the form
LR operator%(L, R);
LR operator&(L, R);
LR operator^(L, R);
LR operator|(L, R);
L operator<<(L, R);
L operator>>(L, R);
where
LR
is the result of the usual arithmetic conversions ([expr.arith.conv]) between types
L
and
R.

For every triple
(L, vq, R),
where L is an arithmetic type,
and R is a floating-point or promoted integral type,
there exist candidate operator functions of the form
vq L& operator=(vq L&, R);
vq L& operator*=(vq L&, R);
vq L& operator/=(vq L&, R);
vq L& operator+=(vq L&, R);
vq L& operator-=(vq L&, R);

For every pair (T, vq),
where T is any type,
there exist candidate operator functions of the form
T*vq& operator=(T*vq&, T*);

For every pair
(T,
vq),
where
T
is an enumeration or pointer-to-member type,
there exist candidate operator functions of the form
vq T& operator=(vq T&, T);

For every pair
(T,
vq),
where
T
is a cv-qualified or cv-unqualified object type,
there exist candidate operator functions of the form
T*vq& operator+=(T*vq&, std::ptrdiff_t);
T*vq& operator-=(T*vq&, std::ptrdiff_t);

For every triple
(L,
vq,
R),
where
L
is an integral type, and
R
is a promoted integral type,
there exist candidate operator functions of the form
vq L& operator%=(vq L&, R);
vq L& operator<<=(vq L&, R);
vq L& operator>>=(vq L&, R);
vq L& operator&=(vq L&, R);
vq L& operator^=(vq L&, R);
vq L& operator|=(vq L&, R);

There also exist candidate operator functions of the form
bool operator!(bool);
bool operator&&(bool, bool);
bool operator||(bool, bool);

For every pair of types L and R,
where each of L and R is a
floating-point or promoted integral type,
there exist candidate operator functions of the form
LR operator?:(bool, L, R);
where
LR
is the result of the usual arithmetic conversions ([expr.arith.conv]) between types
L
and
R.