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*.