How does the C ++ compiler extend the prefix and postfix operator ++ ()?

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 experimented with this to determine how the compiler extended the 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 go to something like "e.operator ++ (2).", but instead I end up with a compiler that complains about some "no match to call" (example) (int) ".

Next, I was curious how "++ e" mysteriously expanded to "e.operator ++ ()", that is, the one that returns a link.

Playing some more, I ended up with:

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

      

Printed 2 and then:

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

      

What's printed 3.

My understanding is that (++ e) returns a reference to an object, which is then added in increments by one, so it makes sense. I also suspect that "++ e ++" is giving post-positional priority here (as I read in another post), so this increments the temporary variable returned by the postfix operator. This also makes sense. This got me thinking about how expressions like

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

      

expandable (they all compile and run with expected results).

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

+3


source to share


1 answer


What is the purpose of the placeholder variable in "operator ++ (int)"?

Because the operator ++

has two different functions, postfix - ++ and prefix - ++. Therefore, when overloaded, there must be two different function signatures.

how does the compiler know which operator ++ () to call,

When your code uses a prefix ++

(for example:) ++e;

, the function with the signature is operator++()

called. When your code uses postfix- ++

(ex :; e++

), the function with the signature is called operator++(int)

, and the compiler will provide an undefined argument to the dummy file.

Technically an implementation operator++(int)

can use the value of a dummy argument. And you can convey your meaning by writing e.operator++(5);

instead e++;

. But this will be considered bad coding style - when overloading operators, it is recommended to preserve the semantics of inline operators so as not to confuse people reading the code.

Note that your current postfix- implementation ++

does not enforce this rule: the normal semantics is that the previous value should be returned; but your code is returning an updated value.

++e++++;

To parse this statement, you need to know about these parsing rules:



  • Tokens are analyzed using the "maximum munch", i.e. it means ++ e ++ ++;

    (and not some unary- operators +

    ).
  • The language grammar determines from these tokens which expressions are the operand of operators. This process can be summarized in a table.

Table counseling for this expression says to you ++(((e++)++))

. Using the extension mentioned above, this can be written in the function call notation:

((e.operator++(0)).operator++(0)).operator++();

      

In this case, these functions must be called left-right, since the member function cannot be entered before the expression is evaluated.

So, suppose we had before this statement Example e(1);

, the following function calls occur in this order:

  • e.operator++(int)

    - sets e.m_i

    to 2

    and returns a temporary (I'll refer to it temp1

    as pseudocode) with temp1.m_i

    as 2

    .
  • temp1.operator++(int)

    - sets temp1.m_i

    in 3

    and returns temp2

    who m.i

    is3

  • temp2.operator++()

    - sets temp2.m_i

    in 4

    and returns a link to temp2

    .

NB. My answer only says that the overloaded operator is a member function. It is also possible to overload ++

(both forms) as non-member. In this case, the behavior will be the same compared to my description, but the expression "written in the function call function" will have a different syntax.

+2


source







All Articles