116

How to overload the operator++ in two different ways for postfix a++ and prefix ++a?

Ciro Santilli OurBigBook.com
  • 347,512
  • 102
  • 1,199
  • 985
rookie
  • 7,723
  • 15
  • 49
  • 59

5 Answers5

176

Should look like this:

class Number 
{
    public:
        Number& operator++ ()     // prefix ++
        {
           // Do work on this.   (increment your object here)
           return *this;
        }

        // You want to make the ++ operator work like the standard operators
        // The simple way to do this is to implement postfix in terms of prefix.
        //
        Number  operator++ (int)  // postfix ++
        {
           Number result(*this);   // make a copy for result
           ++(*this);              // Now use the prefix version to do the work
           return result;          // return the copy (the old) value.
        }
}; 
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • 15
    This code also shows the prefix vs. postfix performance difference. If the object you are returning doesn't fit into a CPU register, then you are doing an expensive copy operation. This is fine if you need to use the pre-incremented value, but if you don't, postfix is much better. An example would be an iterator where you typically use: for(pos=c.begin(); ...; ++pos) {} instead of pos++ – Eric Oct 02 '10 at 16:28
  • 23
    @Eric: You have it correct all the way through apart from a sentence in the middle where you mix. Its prefix that is better. – Martin York Oct 02 '10 at 19:10
  • 1
    If all a postfix does is call `++` on a single member, and the type is constructable from that member's type, one can simplify postfix to `Number operator++(int) {return Number(member++);}` – Mooing Duck Jul 09 '13 at 00:09
  • @MooingDuck: I still prefer the above method as it is DRY. All the code for incrementing is in one place (the prefix increment). Thus if you change behavior you only need to fix the code in one place rather than two. – Martin York Jul 09 '13 at 18:16
  • Is this example missing something important? If operator++() gets called...where does it get incremented? – Stéphane Sep 03 '14 at 10:35
  • @Stéphane: Since it depends on the object how that is implemented. I left that part upto the developer but marked it with `// Do work on this.` – Martin York Sep 03 '14 at 16:41
  • postfix ++ looks very inefficient because it copies the object twice, but is the advantage that it can be made non-throw exception and tread safe? – Damian Mar 23 '16 at 15:22
  • @Damian: The second copy you imply is the return value. In C++03 this would have almost certainly be removed by `NRVO`. In C++11 its an xvalue so its unlikely there will be a copy made. Also take into account these are iterators there size should be trivial so cost is small. Secondly why would an iterator throw an exception! you are more likely to walk into undefined behavior than throw. – Martin York Mar 23 '16 at 15:45
  • @Damian Also, the difference can be moot sometimes. If the type is simple enough, and the return value isn't used, the compiler may be able to optimise a call to the postfix operator into a call to the prefix operator. For example, most if not all modern compilers will treat the loop-expression of `(int i = 0, i < whatever; i++)` and `(int i = 0; i < whatever; ++i)` identically, by silently treating both as if they were `++i`. – Justin Time - Reinstate Monica Mar 31 '16 at 21:58
  • This is a famous question and answer. Can you update it with how to overload `++` when you don't have a class type (like, on an `enum`)? And/or via `friend ++`? – Yakk - Adam Nevraumont Dec 05 '16 at 20:32
  • @Yakk: Already covered in a separate question: http://stackoverflow.com/q/18789535/14065 – Martin York Dec 05 '16 at 23:45
  • 6
    Why does `Number operator++ (int)` take an `int` as a parameter even though you do not use it? – Sean Letendre Sep 09 '17 at 04:10
  • 10
    @SeanLetendre: It does not actually take an int parameter. Its a fake parameter. But the designers of the C++ language had to define a way to distinguish between prefix and postfix function definitions. This is the design decision they made. – Martin York Sep 09 '17 at 05:41
  • @MartinYork, there's just one thing I didn't understand of the postfix/prefix discrimination, and I've realized this misunderstanding of mine just now. It's clear to me that two functions (as the two `operator++` functions in this case) can be distinguished based on their arguments, but how does the compiler distinguish the two calls, given I do not use the functional form (`x.operator++()` vs `x.operator++(1)`), but the operatorial form (`++x` vs `x++`)? Is it just as in the compiler translates the last two to the former two? – Enlico Jan 29 '19 at 19:13
  • 3
    @EnricoMariaDeAngelis: The syntax distinguishes the two. `++x` is prefix and thus calls `operator++()` while `x++` is postfix and thus calls `operator++(int)` – Martin York Jan 29 '19 at 23:40
  • @MartinYork, they could have defined a postfix `operator*` in this way! or an `operator!` for that matter. Something was special about `++` and `--`, I guess it was the fact that `++`, `--`, *by convention* (i.e. by C-language) preserves the type. – alfC Jun 13 '19 at 11:15
36

The difference lies in what signature you choose for your overload(s) of operator ++.

Cited from the relevant article on this subject in the C++ FAQ (go there for more details):

class Number {
  public:
    Number& operator++ ();     // prefix ++: no parameter, returns a reference
    Number  operator++ (int);  // postfix ++: dummy parameter, returns a value
};

P.S.: When I found out about this, all I saw initially was the dummy parameter, but the different return types are actually more interesting; they might explain why ++x is considered more efficient than x++ in general.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
18

You have two ways to overload the two (prefix/postfix) ++ operators for a type T:

Object method:

This is the easiest way, using "common" OOP idiom.

class T
{
    public :
        T & operator++() // ++A
        {
            // Do increment of "this" value
            return *this ;
        }

        T operator++(int) // A++
        {
           T temp = *this ;
           // Do increment of "this" value
           return temp ;
        }
} ;

Object non-member function:

This is another way to do this: As long as the functions are in the same namespace as the object they are referring too, they will be considered when the compiler will search for a fonction to handle ++t ; or t++ ; code:

class T
{
    // etc.
} ;


T & operator++(T & p_oRight) // ++A
{
   // Do increment of p_oRight value
   return p_oRight ;
}

T operator++(T & p_oRight, int) // A++
{
   T oCopy ;
   // Copy p_oRight into oCopy
   // Do increment of p_oRight value
   return oCopy ;
}

It is important to remember that, from a C++ viewpoint (including a C++ compiler viewpoint), those non-member functions are still part of T's interface (as long as they are in the same namespace).

There are two potential advantages of the non-member function notation:

  • If you manage to code them without making them friend of T, then you increased the encapsulation of T
  • you can apply this even to classes or structures whose code you don't own. This is a non-intrusive way to enhance the interface of an object without modifying its declaration.
Craig McQueen
  • 41,871
  • 30
  • 130
  • 181
paercebal
  • 81,378
  • 38
  • 130
  • 159
1

Declare like so:

class A
{
public:
    A& operator++();    //Prefix (++a)
    A operator++(int); //Postfix (a++)

};

Implement properly - do not mess with what everyone knows they do (increment then use, use then increment).

Kate Gregory
  • 18,808
  • 8
  • 56
  • 85
-2

I know it's late, but I had the same problem and found a simpler solution. Don't get me wrong, this is the same solution as the top one (posted by Martin York). It is just a bit simpler. Just a bit. Here it is:

class Number
{
        public:

              /*prefix*/  
        Number& operator++ ()
        {
            /*Do stuff */
            return *this;
        }

            /*postfix*/
        Number& operator++ (int) 
        {
            ++(*this); //using the prefix operator from before
            return *this;
        }
};

The above solution is a bit simpler because it doesn't use a temporary object in the postfix method.

X. Mora
  • 15
  • 4