12 Overloading [over]

12.7 Built-in operators [over.built]

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
:
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.
— end note
 ]
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).
Note
:
In all cases where a promoted integral type is required, an operand of unscoped enumeration type will be acceptable by way of the integral promotions.
— end note
 ]
In the remainder of this subclause, vq represents either volatile or no cv-qualifier.
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 type T 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.
Note
:
As with all these descriptions of candidate functions, this declaration serves only to describe the built-in operator for purposes of overload resolution.
The operator “?:” cannot be overloaded.
— end note
 ]
For every type T, where T is a pointer, pointer-to-member, or scoped enumeration type, there exist candidate operator functions of the form
T       operator?:(bool, T, T);