12 Overloading [over]

12.4 Overloaded operators [over.oper]


12.4.1 General [over.oper.general]

12.4.2 Unary operators [over.unary]

12.4.3 Binary operators [over.binary]

12.4.3.1 General [over.binary.general]

12.4.3.2 Simple assignment [over.assign]

12.4.4 Function call [over.call]

12.4.5 Subscripting [over.sub]

12.4.6 Class member access [over.ref]

12.4.7 Increment and decrement [over.inc]

12.4.7.1 General [over.inc.general]

12.4.7.2 Defaulted function [over.inc.default]


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 and subscripting.
— 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 have at least one function parameter or implicit 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 fundamental 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 fundamental types; this is not required by operator functions.
— end note]
An operator function cannot have default arguments, 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.assign] 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.assign]

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
Analogously, for an expression of the form the operator function is selected by overload resolution, and the expression is interpreted as
( postfix-expression . operator -> () ) -> splice-expression

12.4.7 Increment and decrement [over.inc]

12.4.7.1 General [over.inc.general]

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.¹⁰⁰
[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.
100)100)
Calling operator++ explicitly, as in expressions like a.operator++(2), has no special properties: The argument to operator++ is 2.

12.4.7.2 Defaulted function [over.inc.default]

A defaulted postfix increment or decrement operator function for a type C shall be a non-template function that
  • has a first parameter of type “reference to C” or a first parameter of type “reference to volatile C”, where the implicit object parameter (if any) is considered to be the first parameter,
  • is defined as defaulted in C or in a context where C is complete, and
  • has a declared return type of C.
[Note 1: 
A postfix increment or decrement operator always has a parameter of type int ([over.inc.general]).
— end note]
Name lookups and access checks in the implicit definition ([dcl.fct.def.default]) of a defaulted postfix increment or decrement operator function are performed from a context equivalent to its function-body.
A definition of a postfix increment or decrement operator as defaulted that appears in a class shall be the first declaration of that function.
[Example 1: struct S; S operator++(S&, int) = default; // error: S is not complete — end example]
A defaulted postfix increment or decrement operator function for a type C is defined as deleted if
  • C is a class type for which overload resolution ([over.match]), as applied to direct-initialization of a variable of type C from an lvalue of type C, does not result in a usable candidate,
  • C has a destructor that is deleted or inaccessible from the context of the function-body, or
  • for an lvalue c of type C, overload resolution as applied to ++c for a postfix increment operator function or --c for a postfix decrement operator function does not result in a usable candidate.
The implicit definition of a defaulted postfix increment or decrement operator function F that is not defined as deleted for a type C is equivalent to C tmp(c); ++c; return tmp; for a postfix increment operator function, or C tmp(c); --c; return tmp; for a postfix decrement operator function, where tmp is a variable defined for exposition only, and c is an lvalue that denotes *this if F is an implicit object member function, or the first parameter of F otherwise.
[Example 2: struct S{ S(const S&) = default; S& operator++() { return *this; } }; S operator++(S, int) = default; // error: incorrect parameter type struct T{ T operator++(int) = default; // OK, defined as deleted }; enum class E1 {}; E1 operator++(E1&, int) = default; // OK, defined as deleted; built-in operator++ // does not exist for enumeration types enum E2 {}; E2& operator++(E2& e); E2 operator++(E2&, int) = default; // OK, not deleted — end example]