12 Overloading [over]

12.4 Overloaded operators [over.oper]

12.4.1 General [over.oper.general]

A declaration whose declarator-id is an operator-function-id shall declare a function or function template or an explicit instantiation or specialization of a function template.
A function so declared is an operator function.
A function template so declared is an operator function template.
A specialization of an operator function template is also an operator function.
An operator function is said to implement the operator named in its operator-function-id.
operator: one of
new delete new[] delete[] co_await () [] -> ->*
~ ! + - * / % ^ &
| = += -= *= /= %= ^= &=
|= == != < > <= >= <=> &&
|| << >> <<= >>= ++ -- ,
[Note 1: 
The operators new[], delete[], (), and [] are formed from more than one token.
The latter two operators are function call ([expr.call]) and subscripting ([expr.sub]).
— end note]
Both the unary and binary forms of
+ - * &
can be overloaded.
[Note 2: 
The following operators cannot be overloaded:
. .* :: ?:
nor can the preprocessing symbols # ([cpp.stringize]) and ## ([cpp.concat]).
— end note]
Operator functions are usually not called directly; instead they are invoked to evaluate the operators they implement ([over.unary][over.inc]).
They can be explicitly called, however, using the operator-function-id as the name of the function in the function call syntax ([expr.call]).
[Example 1: complex z = a.operator+(b); // complex z = a+b; void* p = operator new(sizeof(int)*n); — end example]
The allocation and deallocation functions, operator new, operator new[], operator delete, and operator delete[], are described completely in [basic.stc.dynamic].
The attributes and restrictions found in the rest of [over.oper] do not apply to them unless explicitly stated in [basic.stc.dynamic].
The co_await operator is described completely in [expr.await].
The attributes and restrictions found in the rest of [over.oper] do not apply to it unless explicitly stated in [expr.await].
An operator function shall either
  • be a member function or
  • be a non-member function that has at least one non-object parameter whose type is a class, a reference to a class, an enumeration, or a reference to an enumeration.
It is not possible to change the precedence, grouping, or number of operands of operators.
The meaning of the operators =, (unary) &, and , (comma), predefined for each type, can be changed for specific class types by defining operator functions that implement these operators.
Likewise, the meaning of the operators (unary) & and , (comma) can be changed for specific enumeration types.
Operator functions are inherited in the same manner as other base class functions.
An operator function shall be a prefix unary, binary, function call, subscripting, class member access, increment, or decrement operator function.
[Note 3: 
The identities among certain predefined operators applied to basic types (for example, ++a a+=1) need not hold for operator functions.
Some predefined operators, such as +=, require an operand to be an lvalue when applied to basic types; this is not required by operator functions.
— end note]
An operator function cannot have default arguments ([dcl.fct.default]), except where explicitly stated below.
Operator functions cannot have more or fewer parameters than the number required for the corresponding operator, as described in the rest of [over.oper].
Operators not mentioned explicitly in subclauses [over.ass] through [over.inc] act as ordinary unary and binary operators obeying the rules of [over.unary] or [over.binary].

12.4.2 Unary operators [over.unary]

A prefix unary operator function is a function named operator@ for a prefix unary-operator @ ([expr.unary.op]) that is either a non-static member function ([class.mfct]) with no non-object parameters or a non-member function with one parameter.
For a unary-expression of the form @ cast-expression, the operator function is selected by overload resolution ([over.match.oper]).
If a member function is selected, the expression is interpreted as
cast-expression . operator @ ()
Otherwise, if a non-member function is selected, the expression is interpreted as
operator @ ( cast-expression )
[Note 1: 
The operators ++ and -- ([expr.pre.incr]) are described in [over.inc].
— end note]
[Note 2: 
The unary and binary forms of the same operator have the same name.
Consequently, a unary operator can hide a binary operator from an enclosing scope, and vice versa.
— end note]

12.4.3 Binary operators [over.binary]

12.4.3.1 General [over.binary.general]

A binary operator function is a function named operator@ for a binary operator @ that is either a non-static member function ([class.mfct]) with one non-object parameter or a non-member function with two parameters.
For an expression x @ y with subexpressions x and y, the operator function is selected by overload resolution ([over.match.oper]).
If a member function is selected, the expression is interpreted as
x . operator @ ( y )
Otherwise, if a non-member function is selected, the expression is interpreted as
operator @ ( x , y )
An equality operator function is an operator function for an equality operator ([expr.eq]).
A relational operator function is an operator function for a relational operator ([expr.rel]).
A three-way comparison operator function is an operator function for the three-way comparison operator ([expr.spaceship]).
A comparison operator function is an equality operator function, a relational operator function, or a three-way comparison operator function.

12.4.3.2 Simple assignment [over.ass]

A simple assignment operator function is a binary operator function named operator=.
A simple assignment operator function shall be a non-static member function.
[Note 1: 
Because only standard conversion sequences are considered when converting to the left operand of an assignment operation ([over.best.ics]), an expression x = y with a subexpression x of class type is always interpreted as x.operator=(y).
— end note]
[Note 2: 
Since a copy assignment operator is implicitly declared for a class if not declared by the user ([class.copy.assign]), a base class assignment operator function is always hidden by the copy assignment operator function of the derived class.
— end note]
[Note 3: 
Any assignment operator function, even the copy and move assignment operators, can be virtual.
For a derived class D with a base class B for which a virtual copy/move assignment has been declared, the copy/move assignment operator in D does not override B's virtual copy/move assignment operator.
[Example 1: struct B { virtual int operator= (int); virtual B& operator= (const B&); }; struct D : B { virtual int operator= (int); virtual D& operator= (const B&); }; D dobj1; D dobj2; B* bptr = &dobj1; void f() { bptr->operator=(99); // calls D​::​operator=(int) *bptr = 99; // ditto bptr->operator=(dobj2); // calls D​::​operator=(const B&) *bptr = dobj2; // ditto dobj1 = dobj2; // calls implicitly-declared D​::​operator=(const D&) } — end example]
— end note]

12.4.4 Function call [over.call]

A function call operator function is a function named operator() that is a member function with an arbitrary number of parameters.
It may have default arguments.
For an expression of the form where the postfix-expression is of class type, the operator function is selected by overload resolution ([over.call.object]).
If a surrogate call function is selected, let e be the result of invoking the corresponding conversion operator function on the postfix-expression;
the expression is interpreted as
e ( expression-list )
Otherwise, the expression is interpreted as
postfix-expression . operator () ( expression-list )

12.4.5 Subscripting [over.sub]

A subscripting operator function is a member function named operator[] with an arbitrary number of parameters.
It may have default arguments.
For an expression of the form the operator function is selected by overload resolution ([over.match.oper]).
If a member function is selected, the expression is interpreted as
postfix-expression . operator [] ( expression-list )
[Example 1: struct X { Z operator[](std::initializer_list<int>); Z operator[](auto...); }; X x; x[{1,2,3}] = 7; // OK, meaning x.operator[]({1,2,3}) x[1,2,3] = 7; // OK, meaning x.operator[](1,2,3) int a[10]; a[{1,2,3}] = 7; // error: built-in subscript operator a[1,2,3] = 7; // error: built-in subscript operator — end example]

12.4.6 Class member access [over.ref]

A class member access operator function is a function named operator-> that is a non-static member function taking no non-object parameters.
For an expression of the form the operator function is selected by overload resolution ([over.match.oper]), and the expression is interpreted as
( postfix-expression . operator -> () ) -> template id-expression

12.4.7 Increment and decrement [over.inc]

An increment operator function is a function named operator++.
If this function is a non-static member function with no non-object parameters, or a non-member function with one parameter, it defines the prefix increment operator ++ for objects of that type.
If the function is a non-static member function with one non-object parameter (which shall be of type int) or a non-member function with two parameters (the second of which shall be of type int), it defines the postfix increment operator ++ for objects of that type.
When the postfix increment is called as a result of using the ++ operator, the int argument will have value zero.113
[Example 1: struct X { X& operator++(); // prefix ++a X operator++(int); // postfix a++ }; struct Y { }; Y& operator++(Y&); // prefix ++b Y operator++(Y&, int); // postfix b++ void f(X a, Y b) { ++a; // a.operator++(); a++; // a.operator++(0); ++b; // operator++(b); b++; // operator++(b, 0); a.operator++(); // explicit call: like ++a; a.operator++(0); // explicit call: like a++; operator++(b); // explicit call: like ++b; operator++(b, 0); // explicit call: like b++; } — end example]
A decrement operator function is a function named operator-- and is handled analogously to an increment operator function.
113)113)
Calling operator++ explicitly, as in expressions like a.operator++(2), has no special properties: The argument to operator++ is 2.