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);