57
votes

Can we overload operator++ for pre-increment and post-increment? i.e. calling SampleObject++ and ++SampleObject results correctly.

class CSample {
 public:
   int m_iValue;     // just to directly fetch inside main()
   CSample() : m_iValue(0) {}
   CSample(int val) : m_iValue(val) {}
   // Overloading ++ for Pre-Increment
   int /*CSample& */ operator++() { // can also adopt to return CSample&
      ++(*this).m_iValue;
      return m_iValue; /*(*this); */
   }

  // Overloading ++ for Post-Increment
 /* int operator++() {
        CSample temp = *this;
        ++(*this).m_iValue;
        return temp.m_iValue; /* temp; */
    } */
};

We can't overload a function based only on return type, and also even if we take it as permitted, it doesn't solve the problem because of the ambiguity in call resolution.

Since operator overloading is provided to make built-in types behave like as user-defined types, why we can't avail both pre and post increment for our own types at the same time.

5
Personally, I never implement or write post increment. IMO its use can lead to very complicated code.abergmeier
@LCIDFire it would be quite tricky to implement iterators without it.juanchopanza
With C++20, you get default comparisons (a.k.a. "spaceship operator").DevSolar

5 Answers

101
votes

The postfix version of the increment operator takes a dummy int parameter in order to disambiguate:

// prefix
CSample& operator++()
{
  // implement increment logic on this instance, return reference to it.
  return *this;
}

// postfix
CSample operator++(int)
{
  CSample tmp(*this);
  operator++(); // prefix-increment this instance
  return tmp;   // return value before increment
}
26
votes

The standard pattern for pre-increment and post-increment for type T

T& T::operator++() // pre-increment, return *this by reference
{
 // perform operation


 return *this;
}

T T::operator++(int) // post-increment, return unmodified copy by value
{
     T copy(*this);
     ++(*this); // or operator++();
     return copy;
}

(You can also call a common function for performing the increment, or if it's a simple one-liner like ++ on a member, just do it in both)

13
votes

why we can't avail both pre and post increment for our own types at the same time.

You can:

class CSample {
public:

     int m_iValue;
     CSample() : m_iValue(0) {}
     CSample(int val) : m_iValue(val) {}

     // Overloading ++ for Pre-Increment
     int /*CSample& */ operator++() {
        ++m_iValue;
        return m_iValue;
     }

    // Overloading ++ for Post-Increment
    int operator++(int) {
          int value = m_iValue;
          ++m_iValue;
          return value;
      }
  };

  #include <iostream>

  int main()
  {
      CSample s;
      int i = ++s;
      std::cout << i << std::endl; // Prints 1
      int j = s++;
      std::cout << j << std::endl; // Prints 1
  }
8
votes

[N4687]

16.5.7

The user-defined function called operator++ implements the prefix and postfix ++ operator. If this function is a non-static member function with no 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 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:

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++;
}
0
votes
#include<iostream>
using namespace std;

class increment{
int a;
public:
increment(int x)
{ a=x; }

void operator ++(){
cout<<"pre-increment:";
cout<<++a;}

void operator ++(int){                  /*post version of increment operator takes  int as a dummy parameter*/

 cout<<endl<<"post-increment:";
 cout<<a++;}
};


int main(){
increment o1(4);   
increment o2(4);
++o1;       //pre-increment
o2++;       //post-increment

}

OUTPUT:
pre-increment:5
post-increment:4