How does a C++ compiler expand prefix and postfix operator++()?

Viewed 775

Consider:

class Example
{
private:
    int m_i;

public:
    Example(int i) : m_i{i} {}

    //Post-fix
    Example operator++(int) {m_i++; return *this;}

    //Pre-fix
    Example& operator++() {m_i++; return *this;}

    void print() const {std::cout << m_i << '\n'}
};

I was experimenting with this to determine how the compiler expanded a call to the prefix and postfix operators.

For example, when I write something like this:

Example e = 1;
e++;

I expected it to expand to something like "e.operator++(int)", or taking it a step further, I expected

e++(2);

to expand to something like "e.operator++(2).", but what I get instead is the compiler complaining about some "no match for call to '(Example) (int)'".

Next I was curious as to how "++e" mysteriously expanded into "e.operator++()", i.e. the one that returns a reference.

Playing around some more, I ended up with:

Example e = 1;
++e++;
e.print();

Which printed 2, and then:

Example e = 1;
(++e)++;
e.print();

Which printed 3.

I understand that (++e) returns a reference to the object which is then post-incremented by one, so this makes sense. I also suspect that "++e++" is giving the postfix operator precedence here (as I read in another post), so this is incrementing the temporary variable returned by the postfix operator. This too makes sense. This led me to wonder about how expressions like

++++e
++e++++
++++e++
++++e++++

are expanded (they all compile and run with expected results).

So really, what the hell is going on on the inside and how does the compiler know which operator++() to call, and how are these expressions expanded (especially in the prefix case)? What is the purpose of the placeholder variable in "operator++(int)"?

1 Answers
Related