How is one of these operator overloads different than the other?

n my textbook, Data Structures and Algorithm Analysis in C++ (Fourth Edition) by Mark Allen Weiss, in chapter 3 pages 91 - 102 the book describes its own user-defined implementation of a List class (which is separate from the library class). On page 96 and 97, the book discusses two different operator overloads with the same name but different signatures. On page they are listed thus:

1
2
3
4
5
6
7
8
9
 const_iterator & operator++ ( ) {
     current = current->next; 
     return *this; 
 } 
 const_iterator operator++ ( int ){ 
     const_iterator old = *this; 
     ++( *this ); 
     return old; 
 }


On page 96, the book has this to say about the two different operators with the same name:

At lines 10 to 21 we see the implementation of operator++. Recall that the prefix and postfix versions of operator++ are completely different in semantics (and precedence), so we need to write separate routines for each form. They have the same name, so they must have different signatures to be distinguished. C++ requires that we give them different signatures by specifying an empty parameter list for the prefix form and a single (anonymous) int parameter for the postfix form. Then ++itr calls the zero-parameter operator++; and itr++ calls the one-parameter operator++. The int parameter is never used; it is present only to give a different signature. The implementation suggests that, in many cases where there is a choice between using the prefix or postfix operator++, the prefix form will be faster than the postfix form.


The book makes the claim that the different operator signatures will result in them being called in different contexts. But why would that be? Why would the first version of operator++ having a reference before it and taking no parameters cause it to return the postfix version of ++ instead of the prefix? How would the differences in these two operators cause them to be called differently?
Last edited on
How would the differences in these two operators cause them to be called differently?


This is an admitted oddity in C++.

The problem was to figure out how to specify the postfix operator differently from the prefix operator. One rule that could not be broken to accommodate the situation is the simple fact that functions can't be overloaded by a difference in the return type only.

Keep that in mind for a moment.

The primary difference between the prefix and postfix operators, outside of the fact that postfix happens after an evaluation of the operand, is the fact that the postfix returns a copy, and in particular a copy of the state before the increment was performed. The prefix version merely returns the operand itself (in this case, a reference to it) after the increment is performed.

The awkward solution to the problem that overloading for this difference can't be merely by the return value, it was decided, arbitrarily (after much consternation in discussion I'm sure) that the postfix version would require an unused (and otherwise unnecessary) integer parameter. The compiler merely recognizes this as the postfix version as a matter of convention.

That last sentence is actually the answer here. It is an arbitrary choice deliberately causing the compiler to recognize that form as the postfix operator, and calls it in that circumstance, while the other version is the prefix version.

In discussion I've heard naive students inquire, "why can't we just define the postfix operator as"

v operator ()++ {...}

Yet, that would actually suggest the operator being defined is the function operator "()", which already has it's own validity, but with the apparent syntax error of the following "++".

Actually, that would not be all that bad a solution if it were accepted as an arbitrary interpretation of this one context for these operators (this all applies to '--' too), but alas, it appears the committee (if it was a committee at the time) simply didn't want to take that direction.


Last edited on
Ah, so the answer, in a way, was "just because we need to differentiate between the two and this feels good" or something? Hahaha. That is really interesting though. I didn't know that functions couldn't be overloaded if all they did was return a different type! So like if I wanted two functions that return the same type but have different parameters, I am allowed to do that, but I couldn't have both functions be identical in terms of what parameters they take even if they returned different types (say an int vs. a char*)?
but I couldn't have both functions be identical in terms of what parameters they take even if they returned different types (say an int vs. a char*)?


Let's consider that.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<iostream>
int f(int x, int y)
{
    return x + y;
}

short f(int x, int y)
{
    return x - y;
}

int main()
{
    auto answer = f (10, 5);
    std::cout << answer << std::endl;
}


What does this program print out?

You might argue that the auto keyword makes it ambiguous, and that declaring the type of answer would solve the problem. Well, the same problem would happen if you changed it to float answer;

Topic archived. No new replies allowed.