cpp/language/operators

Customizes the C++ operators for operands of user-defined types.

Syntax
Overloaded operators are with special function names:

@1@ overloaded operator; @2@ ; @3@ allocation function; @4@ deallocation function; @5@ ; @6@ overloaded operator for use in.

Overloaded operators
When an operator appears in an, and at least one of its operands has a or an , then  is used to determine the user-defined function to be called among all the functions whose signatures match the following:

Note: for overloading, , allocation and deallocation see their respective articles.

Overloaded operators (but not the built-in operators) can be called using function notation:

Restrictions

 * The operators (scope resolution),  (member access),  (member access through pointer to member), and  (ternary conditional) cannot be overloaded.
 * New operators such as, , or cannot be created.
 * It is not possible to change the precedence, grouping, or number of operands of operators.
 * The overload of operator must either return a raw pointer, or return an object (by reference or by value) for which operator  is in turn overloaded.
 * The overloads of operators and  lose short-circuit evaluation.

Canonical implementations
Besides the restrictions above, the language puts no other constraints on what the overloaded operators do, or on the return type (it does not participate in overload resolution), but in general, overloaded operators are expected to behave as similar as possible to the built-in operators: is expected to add, rather than multiply its arguments,  is expected to assign, etc. The related operators are expected to behave similarly ( and  do the same addition-like operation). The return types are limited by the expressions in which the operator is expected to be used: for example, assignment operators return by reference to make it possible to write, because the built-in operators allow that.

Commonly overloaded operators have the following typical, canonical forms:

Assignment operator
The assignment operator has special properties: see  and  for details.

The canonical copy-assignment operator is expected to be safe on self-assignment, and to return the lhs by reference:

In those situations where copy assignment cannot benefit from resource reuse (it does not manage a heap-allocated array and does not have a (possibly transitive) member that does, such as a member std or std), there is a popular convenient shorthand: the copy-and-swap assignment operator, which takes its parameter by value (thus working as both copy- and move-assignment depending on the value category of the argument), swaps with the parameter, and lets the destructor clean it up.

This form automatically provides, but prohibits resource reuse.

Stream extraction and insertion
The overloads of and  that take a  or  as the left hand argument are known as insertion and extraction operators. Since they take the user-defined type as the right argument ( in ), they must be implemented as non-members.

These operators are sometimes implemented as.

Function call operator
When a user-defined class overloads the function call operator,, it becomes a type.

An object of such a type can be used in a function call expression:

Many standard algorithms, from to  accept s to customize behavior. There are no particularly notable canonical forms of, but to illustrate the usage:

Increment and decrement
When the postfix increment or decrement operator appears in an expression, the corresponding user-defined function ( or ) is called with an integer argument. Typically, it is implemented as or, where the argument is ignored. The postfix increment and decrement operators are usually implemented in terms of the prefix versions:

Although the canonical implementations of the prefix increment and decrement operators return by reference, as with any operator overload, the return type is user-defined; for example the overloads of these operators for std return by value.

Binary arithmetic operators
Binary operators are typically implemented as non-members to maintain symmetry (for example, when adding a complex number and an integer, if is a member function of the complex type, then only  would compile, and not ). Since for every binary arithmetic operator there exists a corresponding compound assignment operator, canonical forms of binary operators are implemented in terms of their compound assignments:

Comparison operators
Standard algorithms such as and containers such as  expect  to be defined, by default, for the user-provided types, and expect it to implement strict weak ordering (thus satisfying the  requirements). An idiomatic way to implement strict weak ordering for a structure is to use lexicographical comparison provided by std:

Typically, once is provided, the other relational operators are implemented in terms of.

Likewise, the inequality operator is typically implemented in terms of :

When three-way comparison (such as std or std) is provided, all six two-way comparison operators may be expressed through that:

Array subscript operator
User-defined classes that provide array-like access that allows both reading and writing typically define two overloads for : const and non-const variants:

If the value type is known to be a scalar type, the const variant should return by value.

Where direct access to the elements of the container is not wanted or not possible or distinguishing between lvalue and rvalue  usage,  may return a proxy. See for example std.

Because a subscript operator can only take one subscript until C++23, to provide multidimensional array access semantics, e.g. to implement a 3D array access, has to return a reference to a 2D plane, which has to have its own  which returns a reference to a 1D row, which has to have  which returns a reference to the element. To avoid this complexity, some libraries opt for overloading instead, so that 3D access expressions have the Fortran-like syntax.

Bitwise arithmetic operators
User-defined classes and enumerations that implement the requirements of are required to overload the bitwise arithmetic operators, , , , , , and , and may optionally overload the shift operators , , and. The canonical implementations usually follow the pattern for binary arithmetic operators described above.

Rarely overloaded operators
The following operators are rarely overloaded:
 * The address-of operator, . If the unary & is applied to an lvalue of incomplete type and the complete type declares an overloaded, it is unspecified whether the operator has the built-in meaning or the operator function is called. Because this operator may be overloaded, generic libraries use std to obtain addresses of objects of user-defined types. The best known example of a canonical overloaded operator& is the Microsoft class . An example of this operator's use in EDSL can be found in boost.spirit.
 * The boolean logic operators, and . Unlike the built-in versions, the overloads cannot implement short-circuit evaluation.  In the standard library, these operators are only overloaded for std.
 * The comma operator, . Because this operator may be overloaded, generic libraries use expressions such as  instead of  to sequence execution of expressions of user-defined types. The boost library uses  in boost.assign, boost.spirit, and other libraries. The database access library SOCI also overloads.
 * The member access through pointer to member . There are no specific downsides to overloading this operator, but it is rarely used in practice. It was suggested that it could be part of a smart pointer interface, and in fact is used in that capacity by actors in boost.phoenix. It is more common in EDSLs such as cpp.react.