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)"?
source to share
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)
- setse.m_i
to2
and returns a temporary (I'll refer to ittemp1
as pseudocode) withtemp1.m_i
as2
. -
temp1.operator++(int)
- setstemp1.m_i
in3
and returnstemp2
whom.i
is3
-
temp2.operator++()
- setstemp2.m_i
in4
and returns a link totemp2
.
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.
source to share