1. Revision History
1.1. Changes from R1
P3668R1 was seen by EWG at the Sofia meeting, and forwarded to Core for C++29.- 
     Targeted CWG. 
- 
     Added § 9 Polls. 
- 
     Changed initialization syntax to use parentheses following EWG direction. 
- 
     Updated status of P2952 as it did not make the C++26 draft. 
- 
     Add citation to library wording change paper. 
1.2. Changes from R0
- 
     Added discussion of what is already possible in defaulted functions (§ 3.2 = default is a function body) following BSI feedback. 
- 
     Added discussion of the potential to reduce boilerplate further via defaulting templates (§ 5.3 Defaulting Templates) following BSI feedback. 
- 
     Fix to typo in wording. 
2. Motivation and Scope
Postfix increment and decrement operators have a default behaviour which already exists in the mind of every C++ developer - make a copy, increment/decrement the original, and return the copy. The canonical implementation of this default can always be expressed entirely in terms of other operations (prefix increment/decrement and copy-construction), in a manner which is entirely agnostic to any other members or subobjects of the class, e.g.auto copy { * this }; ++* this ; return copy ; 
We propose that this sensible default be codified into the language.
Since C++11 the language has had a mechanism in 
| Currently | With Proposal | 
|---|---|
| 
 | 
 | 
This reduces boilerplate code while still expressing the universally-known meaning of the function. The majority of classes written with postfix operations can now simply default them and get an operator which does the right thing. It reduces the possibility for user error when writing such operators - typical classes won’t need their implementation of such functions checked and debugged; and atypical ones will have their explicitly-defined operators stand out by virtue of not being defaulted.
Standardising a "default" behaviour for postfix operations would also allow us to shrink the library specification, by expressing operations which are specified to be equivalent to the canonical implementation as being default. The authors have identified 53 candidate operations which could be defaulted and remain semantically equivalent to their current behaviour, and have written [P3785] to explore defaulting them.
Note: Most of the examples in this paper are written in terms of the postfix increment operator. The scope of this paper equally covers the postfix decrement operator, however we do not repeat every example for both operators in the interests of saving reader time.
3. Proposal
We propose that the postfix increment operator be a defaultable operator. On an instancec C C tmp = C ( c ); ++ c ; return tmp ; 
We also propose that the postfix decrement operator be a defaultable operator, with the defaulted behaviour being equivalent to
C tmp = C ( c ); -- c ; return tmp ; 
In both cases, if the defaulted function does not have return type 
Note that in order to write a specification which applies to all permutations of the postfix operator, we cannot refer to 
struct S0 { int v ; S0 & operator ++ () { ++ v ; return * this ; } S0 operator ++ ( int ) = default ; }; struct S1 { int v ; S1 & operator ++ () { ++ v ; return * this ; } S1 operator ++ ( this S1 & , int ) = default ; }; struct S2 { int v ; S2 & operator ++ () { ++ v ; return * this ; } }; S2 operator ++ ( S2 & , int ) = default ; 
If 
class foo { //Private foo ( const foo & ); foo & operator ++ (); }; //Defined as deleted foo operator ++ ( foo & , int ) = default ; 
Note that our spelling of initialization syntax of the copy is very slightly different from how the library wording specifies postfix operations on existing iterators, e.g. [istream.iterator.ops], to account for the possibility of a user-defined class defining its copy constructor as 
3.1. Minor Edge Cases
Many details of the behaviour of defaulted operators is already covered in [dcl.fct.def.default] and we not intend to change the existing behaviour. However there are a handful of small edge cases to consider in this design. Our baseline to determine how a defaulted postfix operator should behave is to consider the behaviour when 
3.1.1. Volatile Qualification
3.1.2. Return type of the prefix increment operator
It is possible for the user to define a prefix increment operator for class 
However, the return type of the prefix operator function alone is not enough to guarantee it does a "canonical" operation - it may return a surprising value (e.g. a reference to some other instance of 
With this in mind, we do not impose requirements on the return type of the prefix operator.
3.1.3. Explicit Object Parameter Types
There exists an occasionally-surprising feature of explicit object parameters, namely that the explicit object parameter is not required to be the type of the class on which the function is called. For example, the following code is well-formed:
struct S { operator int () { return 42 ; } auto operator ++ ( this int , int ) { /*...*/ } }; 
Which raises the question of whether such an operator should be defaultable. In such cases, a canonical function definition for postfix increment would still generate well-formed code. However, this does not follow the canonical semantics of a default postfix operation, so should not be valid behaviour when specifying that a class has the default semantics.
Fortunately, this possibility is already accounted for in the current standard. Wording in [dcl.fct.def.default] requires that explicit object parameters of defaulted special member functions have type "reference to 
3.2. =  default 
    It is worth noting that =  default noexcept requires template < typename Range > class my_generic_iterator { //... my_generic_iterator operator ++ ( int ) requires std :: ranges :: forward_range < Range > = default ; my_generic_iterator operator ++ ( int ){ /*...*/ } }; 
Equally, the mechanism to 
4. Prior Art
There are several existing approaches to attempt a similar reduction in boilerplate. Our position is that none of them quite find the best way to express user intent in code, and will examine them here.4.1. Template Solutions via CRTP
It is possible in current C++ to define a mixin class to attach the canonical postfix operation to derived classes, such asstruct incrementable { constexpr auto operator ++ ( this auto & self , int ){ auto cpy { self }; ++ self ; return cpy ; } }; class my_class : public incrementable { //... auto & operator ++ (){ /*....*/ } using incrementable :: operator ++ ; }; 
Where 
4.2. Reflection Solutions
[P3294] notes that generative reflection, when it arrives, could also be used to append postfix operations to classes by defining a metafunction to do the canonical thing, such that a user might:
struct C { int i ; auto operator ++ () -> C & { ++ i ; return * this ; } consteval { postfix_increment (); } }; 
This solution is analogous to the previous example - in both cases the user must define some other code elsewhere to manually implement the canonical operations and place a declaration in their class to attach those operations to it. As before, is a less direct way of spelling what this paper proposes - what the user really wants to say is "give me the default postfix operation"; and C++ already has a standard spelling for this with 
There is also benefit in standardising the way to retrieve this default - multiple libraries might all ship their own 
4.3. Free function template operator ++ ( T & ,  int ) 
   It would be possible to define a free function template postfix operator, which automatically generates the correct operator overloads for the class, for example:
template < typename T > requires std :: copyable < T > && requires ( T t ){ { ++ t } -> std :: same_as < T &> ; } constexpr T operator ++ ( T & val , int ){ T copy = T { val }; ++ val ; return copy ; } 
This approach is opt-out, rather than opt-in, with every copyable and prefix-incrementable class automatically gaining postfix operations whether they make sense or not; and so opens the door to additional surprise features. Even if we wish to try to limit this through constraints, we cannot constrain for all possibilities. It resembles 
It would be possible to engineer an opt-in solution with template metaprogramming, such as some template boolean 
4.4. Automatically Generating More Operators
We are not the first to propose the ability to synthesise postfix operations from prefix operators. This was previously suggested as part of [P1046], which sought to allow the majority of C++ arithmetic operators to be automatically generated from rewrites of other operators. The author has since parked that paper in favour of a more fine-grained proposal in [P3039], which is exclusively concerned with generation ofoperator -> () operator ->* () x ++ 5. Alternatives Considered
5.1. Rewrite Rule
One alternative we considered for this change would be a rewrite rule, similar to the C++20 equality and comparison operator changes, such that 
Ultimately, a rewrite rule is difficult to specify and adds additional traps to the language, so the idea was dropped.
5.2. Supporting Alternative Semantics for Postfix Increment on Iterators
Some generic iterators only use the canonical semantics when the underlying iterator operates on a forward range and falls back to an alternative implementation otherwise, which only increments the underlying iterator (e.g. on 
- 
     It is asymmetric with operator -- 
- 
     This is not the only alternative semantics for postfix increment, e.g. the insert iterators define it as a no-op which only exists to satisfy the requirements of LegacyOutputIterator. 
- 
     Not every class which supports postfix increment and decrement is an iterator; so a solution would need to do nothing surprising on classes which model arithmetic types and other usages. 
It also increases rather than decreases the mental load on the developer to understand what a class does. For example, consider
class my_fun_iterator { //... public : my_fun_iterator & operator ++ (){ ... } my_fun_iterator operator ++ ( int ) = default ; }; class my_input_iterator { //... public : my_input_iterator & operator ++ (){ ... } void operator ++ ( int ) = default ; }; 
Do these two defaulted operations do the same thing? Intuitively, they should; but were we to support an "alternative" semantic we would break this intuition. The only information the user has to determine whether the defaulted operation would perform the "canonical" semantic or the "alternative" semantic is the return type of the function. Disambiguation by return type is not a path we want to walk down, as it is an entirely novel concept which has far broader implications than just getting the correct default behaviour for postfix increment.
While it is good to consider common alternatives which see some consistent use, this is not the universal canonical semantic of postfix increment and we do not seek to include it in the default definition.
5.3. Defaulting Templates
There exists a hypothetical world where the boilerplate of defining the same postfix operator can be reduced even further. Consider this C++23 code:class common_base { int m_Val {}; protected : int increment () { return ++ m_Val ; } public : template < typename Self > Self & operator ++ ( this Self & self ) { self . increment (); return self ; } template < typename Self > Self operator ++ ( this Self & self , int ){ auto copy { self }; ++ self ; return copy ; } }; 
If 
We believe that this is the sensible choice at present. While this reduction in boilerplate is desirable the implications of defaulting function templates are far broader than this example and have a different set of design questions to consider. We would prefer to see a general-purpose solution which might be extensible to other defaulted functions, and believe that such a solution should be its own paper.
6. Other Papers in this Space
While we are not aware of any other papers seeking to automatically generate the canonical definition of postfix operators, there are some papers which are tangentially relevant because they are in a similar space. We shall examine how they may interact with this proposal.
6.1. P3662: Improve Increment and Decrement Operator Syntax
[P3662] suggests an alternative syntax for prefix and postfix operations in order to more naturally disambiguate them, rather than use a phantom 
struct S { auto operator ++ prefix () { ... } // ++s auto operator ++ postfix () { ... } // s++ }; 
With new contextual keywords 
struct S { auto operator ++ prefix () { ... } // ++s S operator ++ postfix () = default // s++ }; 
We have discussed this with the author of P3662, and he agrees that there is minimal possibility of compatibility issues between the two papers. While the design of P3662 seeks to evolve following committee feedback, we would be happy to collaborate to ensure that both papers are able to progress in parallel with minimal issues.
6.2. P2952: auto& operator=(X&&) = default
[P2952] proposes that it should be valid to use placeholder return types in the signatures of explicitly defaulted functions, so long as those types would deduce to the correct return type for the function from the imaginary return statement in the function body. As we require that a defaulted postfix operation on class 
 The behaviour of placeholder return types for a defaulted 
struct C { auto operator ++ ( int ) = default ; //Well-formed, deduces to C decltype ( auto ) operator ++ ( int ) = default ; //Well-formed, deduces to C auto * operator ++ ( int ) = default ; //Ill-formed, deduction fails auto & operator ++ ( int ) = default ; //Ill-formed, C& is not C auto && operator ++ ( int ) = default ; //Ill-formed, C& is not C }; 
We anticipate no compatibility issues between the two papers. As P2952 is currently in the CWG queue for C++29, we include wording relative to it which can be used should it be accepted.
7. Effect on Existing Code
We anticipate no effects on existing code. This change is strictly additive and so only opens up possibilities for new code.8. Implementation Experience
None yet.9. Polls
This paper was seen by EWG at the Sofia meeting. The following poll was taken:P3668R1: Forward 'Defaulting Postfix Increment and Decrement Operations' for CWG for inclusion in C++29.
| SF | F | N | A | SA | 
|---|---|---|---|---|
| 10 | 13 | 1 | 0 | 0 | 
Result: Consensus
10. Proposed Wording
We tentatively propose making minimal alteration to [dcl.fct.def.default] and instead defining the behaviour and properties of defaulted postfix operations in a new clause [over.inc.default]. This follows the lead of the C++20 comparison changes to defaulted functions, which were largely defined in their own [class.compare.default] clause. We will, however, modify it to note the existence of defaulted postfix operations:
Modify §9.6.2 [dcl.fct.def.default] as follows:
1 A function definition whose function-body is of the form
; is called an explicitly-defaulted definition. A function that is explicitly defaulted shall= default 1.1 - be a special member function ([special])
or a, comparison operator function ([over.binary], [class.compare.default]), or postfix increment or decrement operator([over.inc.default]), and1.2 - not have default arguments ([dcl.fct.default]).
When adding the clause to define defaulted postfix operations, we note that existing wording in [over.inc] saves repetition by describing decrement operators as analogous to their increment counterparts. While we of course must define the behaviour of a defaulted decrement operator, we hope to use the same principle to avoid other repetition.
Add clause §12.4.7.1 [over.inc.default] as follows:
1 A non-template postfix increment operator function may have an explicitly defaulted definition ([dcl.fct.def.default]). Such a function operating on some class type
shall:C 1.1 - be a non-static member of
or a non-member function, andC 1.2 - be defined as defaulted in
or in a context whereC is complete, andC 1.3 - have two parameters of (possibly different) type "reference to
" andC respectively, where the implicit object parameter (if any) is considered to be the first parameter, andint 1.4 - have the return type
.C If type
does not have a declared copy constructor ([class.copy.ctor]) or prefix increment operator which is accessible from a context equivalent to the function-body of a defaulted postfix increment operator function, it is defined as deleted. A definition of a postfix increment operator function as defaulted that appears in a class shall be the first declaration of that function.C [Example 1:
struct S ; S operator ++ ( S & , int ) = default ; //error: S is not complete 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 }; ]
2 A non-template postfix decrement operator function also may have an explicitly-defaulted definition, and is handled analogously to the postfix increment operator function.
3 The behaviour of a defaulted postfix increment operator function operating on instance
of class typec shall be equivalent to:C C tmp = C ( c ); ++ c ; return tmp ; The behaviour of a defaulted postfix decrement operator function operating on instance
of class typec shall be equivalent to:C C tmp = C ( c ); -- c ; return tmp ; 
10.1. Wording relative to P2952
If [P2952] were to be accepted, we would additionally modify §12.4.7.1 [over.inc.default] as follows:
4 If the declared return type of a defaulted postfix increment operator or defaulted postfix decrement operator contains a placeholder type, its return type is deduced as if from
, wherereturn r is an lvalue reference to an object of the type on which the operator is invoked.r