3

I am trying to find the rationale behind having the re- and post- versions of the increment and decrement operators overloadable separately.
In my mind, and in every implementation I have ever seen of these operators for any type of class, these are the same operator (=do the same thing) and just differ in when it is called.
It would seem much more logical to me that the designers of C++ would have had one ++ operator, and the compiler would call it as needed, either before or after reading the value (or, more likely, at the previous or next sequence point, which I think is equivalent)

So, the question is: Does anyone have an example of a case/class where these might not be implemented the same? Or does anyone know/guess the rationale behind this design choice?


For those that prefer to look at code than read text in a question, here is the summary:

For what type T (a user defined class representing anything you want) would it make sense for the following 2 lines to not have the same side effects:

T v;

v++;
++v;

EDIT
To quote @Simple's comment below, which I hope clarifys the question:

Why post-increment (overloading) is in the language if the compiler can just do a copy itself and do the pre-increment


EDIT 2
Since the question is apparently unclear to many, here is another explanation:

Consider the following two lines:

b = a++;
b = ++a;

If it was one operator (for the sake of argument, I will call the operator +a+), the first line would be translated by the compiler into

b = a;
+a+;

and the second into

+a+;
b = a;
Baruch
  • 20,590
  • 28
  • 126
  • 201
  • 4
    Considering that they kinda *do* do two different things even when they do the same thing... – cHao Nov 05 '13 at 15:55
  • 1
    I don't know why do you say the are the same, the implementations are usually different – Karoly Horvath Nov 05 '13 at 15:56
  • Because a post-increment operator may well *not* work the way you (and many others) think it does. – WhozCraig Nov 05 '13 at 15:56
  • Curiously, the side effects are (traditionally) the same. The difference lies in the actual value of the functions. – Omaha Nov 05 '13 at 15:56
  • 1
    How about `T x=v++;` and `T x=++v;`? – Beta Nov 05 '13 at 15:57
  • exactly. you picked a bad example. you throw away the value of those expressions. – Karoly Horvath Nov 05 '13 at 15:57
  • @KarolyHorvath No, the example is on purpose. If those two always do the same thing then my point is valid. One operator would be enough, with the compiler calling it either at the previous or next sequence point – Baruch Nov 05 '13 at 16:00
  • 1
    @baruch Is your question why not just use one *definition* for both operations? . They're *not* the same, and not for the reasons being expunged in answers below. Further, that you "know this" regarding one of those inaccurate answers probably explains why you're asking the question. – WhozCraig Nov 05 '13 at 16:01
  • But they *don't* always do the same thing. *What are you asking?* – Beta Nov 05 '13 at 16:01
  • 4
    Post-increment can always be implemented in terms of pre-increment. He's asking why post-increment (overloading) is in the language if the compiler can just do a copy itself and do the pre-increment. – Simple Nov 05 '13 at 16:02
  • 1
    @Simple Phrased like that, the question makes a great-deal more sense. – WhozCraig Nov 05 '13 at 16:04
  • Thank you @Simple for rewording it in a way I hope will be clearer to all – Baruch Nov 05 '13 at 16:04
  • @baurch: what you are saying doesn't make sense. just because *your* example works with it, it doesn't mean other code would too. you're relying only part of what those operators do. – Karoly Horvath Nov 05 '13 at 16:04
  • @Simple: No, I think he's asking why we have both operations, when we could get by with just one of them. Just as we don't need `for` loops when we have `while` loops, and we don't need `const` at all. It's hard to tell, the title of his question doesn't match his text. – Beta Nov 05 '13 at 16:07
  • @baruch I would have to check the standard to see whether the resulting value of the operand itself shall be defined as the same for both. Never mind the return value computation, which is where most people, especially academia, think they know how each work and are usually incorrect regarding post-. If the standard does *not* explicitly state the two are operand-value-equivalent, that would explain why two different operators are distinctly accounted. – WhozCraig Nov 05 '13 at 16:08
  • @Beta No, Simple is right. I am sorry if the question was unclear – Baruch Nov 05 '13 at 16:11
  • Your question is **still** unclear. Are you asking why post-increment isn't always implemented in terms of pre-increment, or why post-increment is in the language at all? – Beta Nov 05 '13 at 16:13
  • @WhozCraig, the resulting value of the operand at which point? You really should distill all those comments into a clearer answer. – StoryTeller - Unslander Monica Nov 05 '13 at 16:14
  • 3
    The question can be expanded to: why can't all of the relational operators just be implemented in terms of `operator<`; why can't `operator!=` just be implemented in terms of `operator==`; why can't all of the arithmetical operators be implemented in terms of `operator@=`, etc. The answer is, really, just because someone/some people thought it would be a good idea if these could do different things back in 1998. – Simple Nov 05 '13 at 16:15
  • @Simple Maybe because sometimes you don't need `operator X` but `! operator X`. Now how would you describe that if you were only allowed to implement `operator X`? – RedX Nov 05 '13 at 16:20
  • @RedX this is getting into language design terrority. I was just elaborating the question. `operator!` would just be a built-in (no overloading that operator) and the relational/equality operators would be required to return `bool`. `!(x < y)` would be the same as writing `x >= y` in that they would both call `operator<` and then the built-in `operator!`. – Simple Nov 05 '13 at 16:36

8 Answers8

2

Pre increment increments the variable before the rest of the statement so for example

x = 2;
y = ++x;

y == 3;
x == 3;

Whereas post increment does the increment after the rest of the statement,

x = 2;
y = x++;

y == 2;
x == 3;

Pre increment is slightly faster so it should be preferred. Something to note is that when both operators are used in one statement the behaviour is undefined, so something like

x = 5;
x = x++ + ++x;

will give different results in different languages.

Eamonn McEvoy
  • 8,876
  • 14
  • 53
  • 83
  • I know this. The question is why are these 2 operators, and not 1 operator that is called at different points – Baruch Nov 05 '13 at 15:57
  • Psh. The compiler could easily optimize away the difference if there weren't two separate operators. (In fact, it'd be the one responsible for making `x++` work properly rather than trusting that the code did so.) The question is *why* there are two separate operators -- that is, where would it make sense to have them do anything besides get the value before or after assignment. – cHao Nov 05 '13 at 16:05
  • It should be noted that virtually all modern compilers will optimize away the temporary if you use post-fix instead of prefix (e.g. when writing a for-loop), so the performance issue is no longer an issue. – Zac Howland Nov 05 '13 at 16:49
2

How would you implement a generic version of post-increment ?

I guess: T operator++(int) { T tmp(*this); ++*this; return tmp; }

What if my type is non-copiable, or expensive to copy ?

Well, I'd would prefer:

Proxy operator++(int) { return Proxy(++*this, 1); }

And then have things like:

bool operator==(Proxy const& left, T const& right) {
    return left.value - 1 == right.value;
}

Why post-increment (overloading) is in the language if the compiler can just do a copy itself and do the pre-increment ?

Because your assumption that the compiler can do the copy is erroneous, and even when it holds might be too costly.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
1

This distinction becomes important in iterators over complex types. The expression

*it++

gives me the object the iterator currently points to, and increments the iterator. If the data would normally not be kept in memory after the iterator advances, returning the previous object becomes difficult. There are two approaches to this:

  1. keep a copy in the postincrement
  2. advance after delay

The former method still has to return something that behaves like an iterator (at least with regard to operator* and operator->, but cannot be a pointer because it also has to keep ownership of the copy of the object, so a proxy is returned:

struct iterator {
    value_type value;

    struct proxy {
        value_type value;
        value_type &operator*() { return value; }
        value_type *operator->() { return &value; }
    };

    value_type &operator*() { return value; }
    value_type *operator->() { return &value; }
    iterator &operator++(); // actual increment code
    proxy operator++(int) { proxy ret = { value }; ++*this; return ret; }
};

If creating a copy is expensive as well and should be avoided, you can also delay the increment:

struct iterator {
    value_type value;
    bool needs_increment;

    value_type &operator*() { if(needs_increment) ++*this; return value; }
    value_type *operator->() { if(needs_increment) ++*this; return &value; }
    iterator &operator++(); // actual increment code, resets needs_increment
    value_type *operator++(int) { needs_increment = true; return &value; }
};
Simon Richter
  • 28,572
  • 1
  • 42
  • 64
0

Because of the separate semantics of these operators for built-in types. The value of the expression differs between pre and post increment/decrement, even though both change the operand.

int a = 1;
(a++) == 1;
a = 1;
(++a) == 2;

Allowing to overload them separately permits creating similar semantics for the return value.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • This doesn't answer the question. I know this. But this could still be achieved if they were one operator, by calling it either before or after the instruction that uses it. – Baruch Nov 05 '13 at 15:58
  • @baruch, what do you mean by "calling it either before or after the instruction that uses it"? – StoryTeller - Unslander Monica Nov 05 '13 at 16:00
  • If it was one operator (for the sake of argument, I will call the operator `+a+`), your first line would be translated by the compiler into `a==1; +a+;` and the second into `+a+; a==2;` – Baruch Nov 05 '13 at 16:03
  • @baruch: So... you want the definitions of these operators built into the compiler, rather than written in code? – Beta Nov 05 '13 at 16:06
  • @baruch, and what if the copy is very expansive? Or even impossible (the copy c'tor is private)? Calling the copy c'tor may not be trivial. – StoryTeller - Unslander Monica Nov 05 '13 at 16:06
  • @Beta I want these to be 1 operator, not 2! – Baruch Nov 05 '13 at 16:06
  • @baruch: So you want `++a` and `a++` to do the same thing? Or you want `a++` and `++a` to be banned in favor of `+a+`, which will do the same thing as `a++`? – Beta Nov 05 '13 at 16:10
  • @Beta I want them to do the same thing, but be used as different values. – Baruch Nov 05 '13 at 16:12
  • @baruch: I've read that comment several times, and I can't make any sense of it. I'm out. – Beta Nov 05 '13 at 16:14
  • 1
    @baruch they're not one operator, so you're going to be waiting awhile. The question in general-comment is more interesting anyway. I.e. Why can't the compiler generate proper temp-value post-increment using pre-increment implementation, thereby allowing you to have only a `operator++()` (assuming you don't provide your own post-increment override). If that is the real question its an interesting one, otherwise this is getting lame fast. – WhozCraig Nov 05 '13 at 16:14
  • @Beta: As i understand it, he would like to see one "increment" operation, and the compiler would arrange the calls to it so that the right thing happens. – cHao Nov 05 '13 at 16:15
  • @WhozCraig That is my question! – Baruch Nov 05 '13 at 16:17
  • 1
    @baruch and my comment regarding this is likely the reason, but I've not taken the time to look it up. I'm *guessing* (dangerous to do with the standard) that post-increment is in no way defined *by the standard* as an equivalency to pre-increment (or vice versa) precisely because they're two different operators. it would be like defining `operator -(val)` as equivalent to `operator +(-val)`. The standard goes to great lengths to define operators independently for maximum flexibility and directly conclusive implementations. (again, just a stab at it, but its would seem reasonable). – WhozCraig Nov 05 '13 at 16:22
  • @baruch And it turned out to be an interesting question, after much malaise, so I have to +1 it. – WhozCraig Nov 05 '13 at 16:23
  • @cHao The compiler already does do that. If you use the post-increment, but do nothing with the return value, it will optimize it for you and will be the same as if you had (properly) used the prefix-increment. – Zac Howland Nov 05 '13 at 17:12
  • @ZacHowland: Thing is, with the operators being different, it can only do so much. It has to call the post-increment version, or the observable behavior can change. And the post-increment operator's need to copy the old value is the main cause of the performance difference. Unless the code is inlined, i'm not sure how that copy could be optimized away. – cHao Nov 05 '13 at 18:22
  • @cHao you are forgetting that it is a high level language. When the compiler gets through with it, it is in assembly. The compiler will (quickly) see that you are storing a result in a register and then never using it, and will eliminate that operation entirely. That is usually done in the first pass of an optimization. This has been discussed on SO previously: http://stackoverflow.com/a/6927125/529761 and http://stackoverflow.com/a/7436284/529761 – Zac Howland Nov 05 '13 at 18:53
  • @ZacHowland: The compiler can't as easily eliminate code in other translation units. If the function is being called rather than inlined, and any other code might use the return value, it will still do the copy. (The compiler would rather be slow than violate the as-if rule.) The other option would be to generate separate code for functions that return a value the caller ignores...but that leads down a very deep rabbit hole. – cHao Nov 05 '13 at 20:00
  • @cHao: As I stated, it has been discussed before, and *proven* (e.g. compared the assembly output). With the exception of some rather complex objects, the compiler can, and will, see the use of a temporary that is *not* used and eliminate it. – Zac Howland Nov 05 '13 at 20:38
  • @ZacHowland: Note that both of your links regard C++ library template classes, which are almost always incorporated into the current translation unit. Many of the optimizations possible in that case do not apply well or at all across TU boundaries; the compiler won't modify code it's not compiling. (BTW, Locals. *Not* temporaries. The two are different, and optimizations like RVO don't quite apply to locals. There are other factors at work there.) – cHao Nov 05 '13 at 22:54
  • @cHao Unless your return value is dependent on a branch (in this case it is not), RVO can be applied to locals. And if you notice, the `T operator++(int)` version returns by copy - meaning it *is* a temporary. When the assembly is created, if the return value is not used (e.g. there are no dependencies on it), the compiler may eliminate that instruction. In doing so, it also removes the dependency for the assignment of the local, so that can also be removed. That leaves you with the same assembly as the pre-increment. – Zac Howland Nov 05 '13 at 23:07
  • So yes, except in the case of complex objects with complicated copy-constructors, the compiler can and more than likely will optimize away the programmer's mistaken use of the post-increment. – Zac Howland Nov 05 '13 at 23:08
  • @ZacHowland: No, it won't -- at least not without you specifically telling it to. I just tested it in g++ and clang++; if the function is not in the same translation unit, even at -O3, the local triggers a copy. And literally the only difference at all between `a++;` and `foo b = a++;`, was the value of one of the addresses passed. – cHao Nov 06 '13 at 04:54
  • @ZacHowland, do consider going into the chat instead of blasting my inbox with notifications. – StoryTeller - Unslander Monica Nov 06 '13 at 10:20
0

Look at the following example

int i = 5;
int x = i++;
cout << i << " " << x;

This will print

6 5

int i = 5;
int x = ++i;
cout << i << " " << x;

This will print

6 6

So what can we infer?
In post-fix, the value of i is assigned to x first and then i is incremented
In pre-fix, the value of i is incremented first and then assigned to x

galdin
  • 12,411
  • 7
  • 56
  • 71
  • 1
    `The precedence of post-fix > precedence of assignment operator > precedence of pre-fix` <-- that is not accurate. – Zac Howland Nov 05 '13 at 16:43
0

I think that the problem is related to the order of evaluation of (sub)expressions and the time of applying of side effects. For example in C# the order of evaluation of (sub)expressions is deterministic and side effects are applied at once. For example consider the following C# code

int x = 0;
int y = x++ + ++x;

This code has defined behaviour in C#. So you can implement only one increment operator and the compiler will use it the appropriate way.

C++ has no such a possibility. The order of evaluation of (sub)expressions is unspecified and side effects are not applied at once.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

Perhaps something in a threaded environment that implements lazily? For ++a you want it to block until it has updated a so you get the updated value back, but for a++ you just send the signal and get on with things.

-1

They are two separate operators because they do two different (albeit related) things.

Pre-increment/decrement will increment/decrement the variable and return the new value.

int i = 0;
int j = ++i; // j is now 1

Post-increment/decrement will increment/decrement the variable and return the old value.

int i = 0;
int j = i++; // j is now 0

In general, the implementation of these operators looks like this (for some type T):

T& T::operator++() // prefix overload
{
    *this = *this + 1;
    return *this;
}

T T::operator++(int) // postfix overload
{
    T prev = *this;
    ++(*this); // call prefix overload
    return prev;
}

As you can see, the prefix overload does not need an extra copy of the type, while the postfix version does.

As the bulk of the comments center around the question of why this is the case:

The short answer is: Because the C standard says so (and C++ inherited it from C).

The longer answer is:

++a and a++ are simply shorthand notation for calling specific functions. ++a (for a given type T) maps to either T& T::operator++() or T& operator++(T&) and a++ maps to either T T::operator++(int) or T operator(T&, int). As with all operators, you (as the programmer) can define them to do anything you want with respect to your corresponding type (Note: it is generally considered bad practice to overload an operator to do something strange, but the standard does not stop you from doing so). In general, if you are defining a type (e.g. an iterator), you would make it match the behavior of a built in type (e.g. a pointer) by providing a similar interface (i.e. overloading the proper operators). However, you could decide that you want operator++() to perform the quadratic formula and operator++(int) to take a Fourier Transform. As they are 2 separate functions, that is allowed. If the compiler was allowed to infer operator++(int) based on the on premise that it would be defined in terms of operator++(), they would be tied together.

Operators in C++ are nothing more than shorthand notation for function calls. While it is common to implement several operators in terms of others, it is not required by the standard, and thus the compiler cannot make such an assumption. If it were required by the standard, then there would be a lot of assumed behavior to keep track of.

Additionally, the behavior of ++a and a++ is a carry-over from C. There is a lot of code that exists that utilizes the behavior of one or the other, and changing that in the C++ standard would break compatibility with C (unless you also made the change in the C standard). As there is a lot of existing code that utilizes the behavior of these operators, you would be potentially making a large breaking change.

While it is quite common to implement post-increment in terms of pre-increment, you really should think of these two functions as different functions (much the same way you think of operator== vs operator!=, operator<, operator>, etc. Just because something is common does not mean the standard will, or even should, make it a requirement.

Zac Howland
  • 15,777
  • 1
  • 26
  • 42
  • But when does it make sense for `x++` to be a separate operator, if pretty much every sane post-increment overload is basically the same as the one you have here? Why couldn't the compiler have been made to generate code that does exactly what you've done with your postfix overload? To, say, turn `T i; T j = i++;` into `T i; T j = i; ++i;` ? At that point even the performance difference between `++i` and `i++` could go away until you assigned the result somewhere. – cHao Nov 05 '13 at 16:36
  • The compiler knows nothing about the purpose of your class; it only knows what you tell it. There are times where you do not want a post-increment and want everything to be done with pre-increment only (or vice versa). Having the compiler make assumptions about things is how you end up with unpredictable code. – Zac Howland Nov 05 '13 at 16:42
  • The purpose of your class shouldn't really involve enforcing syntax. But if you wanted to outlaw post-increment, all you'd have to do is make the class not copy-assignable or copy-constructible. If you allow either one, people already have a trivial workaround anyway for your refusal to allow post-increment, and the lack of an operator for it appears as an oversight rather than a design decision. – cHao Nov 05 '13 at 16:48
  • Making a class non-copyable has a *lot* of other side effects. If you were, for example, writing an iterator class and only wanted to allow pre-increment, then making the entire class non-copyable just to do that would make your entire iterator class unusable. You are confusing the syntax with what it actually is: an interface. `++a` is shorthand for a call to `operator++()` while `a++` is shorthand for a call to `operator++(int)`. They are 2 separate functions. – Zac Howland Nov 05 '13 at 16:55
  • The whole point (and in fact the very title of the question!) is, *why* are they two separate functions? When does it not make sense for them to do the same thing, with the only difference being whether the old value or the new one is returned (a difference which could have been handled by the compiler)? You haven't really answered that; you're going on about outlawing syntax, but ignore the changes that would be required to make such an arbitrary decision useful, when those changes would themselves prevent post-increment from working anyway. – cHao Nov 05 '13 at 17:02
  • But they do **not** do the same thing. They return very different values. They do *half* of the same thing (they both increment, but return differently). You are assuming that because they both increment, they are the same. They are not. I haven't said anything about "outlawing" syntax - I was pointing out that *you* were caught up on the syntax. They are 2 separate functions with 2 different purposes. You are asking why they cannot be 1. The short answer to that is because they are not designed for the same purpose (which I've said in several different ways). – Zac Howland Nov 05 '13 at 17:09
  • Then they should not have the same name. If they weren't both intended to *increment*, then they've both been horribly misnamed this whole time. – cHao Nov 05 '13 at 17:09
  • They do not have the same name. `operator++()` and `operator++(int)` are 2 **different** names. – Zac Howland Nov 05 '13 at 17:10
  • Sorry, but no. The name is `++` or `operator ++`; that's what code everywhere will call it. The *signature* (for post-increment) is `T T::operator++(int)`. And note that the signature itself is an ugly hack; there is no useful value being passed to the post-increment operator. They had to *invent* a way to separate pre- from post-, because they couldn't go by the name alone. – cHao Nov 05 '13 at 17:13
  • /facepalm. Please tell me you did not just state that the signature of a function is not it's name ... It is a shame you cannot -1 comments. `++` is a shorthand notation. The *name* (aka the *signature* aka the actual function being called) is either `operator++()` or `operator++(int)` depending on which shorthand you use. If you cannot see that, then don't even bother to understand differences in `const` vs `non-const` functions ... – Zac Howland Nov 05 '13 at 17:18
  • No, the signature of a function is not its name. The name is *part* of the signature, but is not the whole thing. Signatures are for the compiler's benefit; without them, it couldn't enforce its rules. Names are for humans, and are only useful if objects or functions with the same name do the same thing. – cHao Nov 05 '13 at 17:23
  • @cHao /double-facepalm No, no, no, and no. In C-based languages, the signature of a function *is* how you identify which function is being called, and is *thus* the name of the function. You are, again, getting caught up in the shorthand syntax, which was created in C as a convenience. `++a` and `a++` do **not** use the same functions, therefor they are using 2 separate names ... and which is why the are separate in the standard (one called "pre-increment" and the other called "post-increment" - which would be their human-readable names if you wanted to play with semantics). – Zac Howland Nov 05 '13 at 17:28
  • Signatures and names are not the same thing. C++11 draft, §1.3.17 [defns.signature]: "**signature** : name, parameter type list (8.3.5), and enclosing namespace (if any) [ Note: Signatures are used as a basis for name mangling and linking.— end note ]" That is, `void a()` and `void a(int)` have the same name, but different signatures. – cHao Nov 05 '13 at 17:35
  • Section 1.3 lists the definitions. If you notice, "name" is not one of them. Signature *is*. You are playing with semantics. The main point is: they are 2 separate functions that do similar, but different things. And just like all other operators (e.g. `operator!=` could be written in terms of `operator==`, or even `operator<`), the compiler lets the programmer overload them all individually. Attempting to let the compiler *assume* a given behavior for an operator would result in unexpected behavior (e.g. the ability to use algorithms that the class is not really designed to support). – Zac Howland Nov 05 '13 at 17:53
  • Section 13.5.7 discusses the behavior of pre- and post-increment operators. 13.6 talks about the built in versions. – Zac Howland Nov 05 '13 at 17:59
  • §8.3.5/5: "A single name can be used for several different functions in a single scope; this is function overloading (Clause 13)." If names and signatures were the same thing, this statement alone would make signatures useless. The point is that `operator++()` and `operator++(int)` have the same name, regardless of their signatures...and if they do two different things without a damn good reason, that's bad design by most if not all definitions. The big question, which you *still* haven't answered, is whether/when there is a good enough reason for them to differ to justify distinct signatures. – cHao Nov 05 '13 at 18:08
  • "The big question, which you still haven't answered..." I gave you one example in my answer. I gave you another in the comments. "if they do two different things without a damn good reason, that's bad design by most if not all definitions." They can maintain the same name because they do similar operations. It is the same principle that allows for `T& operator[]` and `T& operator[] const`. Both do the *basically* the same thing, but not entirely. – Zac Howland Nov 05 '13 at 18:51
  • Both examples are easily refuted. The postfix example in your answer is pure boilerplate; if prefix vs postfix were the compiler's responsibility rather than the programmer's, you'd have one operator to implement. You'd have identical functionality and better optimizability, with less code. In the example in the comments, you're hung up on people not being able to say `T a = b++;`, but handwave away the fact that people can say `T a = b; ++b;` to trivially bypass it. Fun part is, if you make the class uncopyable to prevent that, a compiler-generated postfix operator would break too. – cHao Nov 05 '13 at 19:10
  • You are missing the point entirely. I expounded upon it more in the answer is it is clear you were not getting it. Operators in C++ are nothing more than shorthand notation for function calls. There is no real relationship to them except that which the programmer provides. That is, while it is common to implement post-increment in terms of pre-increment, it is not required. Making such a requirement would reduce the number of available operators, and thus reduce the flexibility the programmer has in terms of defining an interface for their objects. – Zac Howland Nov 05 '13 at 19:16
  • If all increments were pre-increments, why would we not say that all comparisons should be less-than? All arithmetic operations should be plus? All division operations should be multiplication? Each of these operators *can* be implemented in terms of others, but doing so reduces your ability to write easily readable code. – Zac Howland Nov 05 '13 at 19:18
  • There being different functions for prefix vs postfix is the very thing being questioned. You don't get to say it's that way "because they're two different operators", and then say they couldn't be one operator "because they do different things", especially when you *implement one almost entirely in terms of the other*, demonstrating the one difference we all already knew (and one the compiler could handle trivially). If you want to prove your point, show an example where the functionality differs in some *other* way that's not universally perceived as broken. – cHao Nov 05 '13 at 19:31
  • All increments don't have to be pre-increments. The compiler, upon encountering a post-increment, could simply generate inline code that does the same thing as your answer had to include a member function to do (store the old value; call the real increment operator; return the old value). The difference is that it wouldn't require implementing a separate post-increment operator, and the resulting code being inlined basically by definition would make the optimizer's life easier. – cHao Nov 05 '13 at 19:38
  • I'll try to type slowly as you apparently do not read for content well. I did *not* say they *couldn't* be one operator; I said doing so would reduce the flexibility of the language. As the goal of the 2 operators (on basic types) is different, eliminating one of them would 1) break a lot of previously written code, 2) break the compatibility with the C language (C++ is a superset of C, this change would make it a cross-set), 3) you would remove one potential shorthand notation (reducing the number of available shorthand notations you can overload for your own purposes). – Zac Howland Nov 05 '13 at 20:45
  • "especially when you implement one almost entirely in terms of the other" - As I stated earlier, that is the same for **all** of the logical operators as well. Why are you not frustrated about the existence of `operator>` when there is already `operator<`? Or the existence of `operator!=` and `operator==` at all? They all are primarily implemented in terms of `operator<`. "your answer had to include a member function to do" - It does **not** need to be a member function (as I explained already). – Zac Howland Nov 05 '13 at 20:48
  • "and the resulting code being inlined basically by definition would make the optimizer's life easier." - Again, you are forgetting that C++ is a high level language. The first thing the compiler does is convert it to assembly ... and that is where the optimizations start. Not in the C/C++ level. You are not doing anything for the optimizer by changing the syntax at a high level. – Zac Howland Nov 05 '13 at 20:49
  • The flexibility of the language is not an issue here; you would be strung up somewhere if `a++;` and `++a;` had any significant difference other than whether the new or old value is returned. And no one here has argued for eliminating them from the language; the entire point was that if they *were* eliminated, there would be no loss of expressivity -- just a bit less code to write. Apparently you don't handle hypotheticals well. – cHao Nov 05 '13 at 22:32
  • As for the other operators, related or not, they don't have the same name. `!=` doesn't have to do the same thing as `==`. Even with `-` and `+`, which are both unary and binary operators, the difference between `+y` and `x+y` is pretty clear. With `++`, though, you have the same characters representing two potentially totally different operations. Quite frankly, that's false flexibility; you'd be strung up if they ever actually *were* significantly different. So instead, you slavishly write the same `T operator++(int)` you've written hundreds of times before, just with a different T. – cHao Nov 05 '13 at 22:42
  • @cHao SO isn't meant to handle hypotheticals (those get closed as they are primarily opinion based). I was answering what *is* and pointing out the consequences of your attempted "what could be". In a nutshell, if you assumed post-increment is always in terms of pre-increment, and you were writing an iterator class that did not support post-increment (that is, it always did a pre-increment - or vice versa), you would have no way to do it. As it is now, you can make both pre and post behave the same, if you wanted to. – Zac Howland Nov 05 '13 at 22:56
  • We already know what *is*. Take another look at the top of this page; the OP is already aware that the two are separate. The very question being asked was why it *should be*. What this answer is totally lacking, is any decent answer to that question. An answer saying "cause it's like this" is either begging the question, or simply misunderstanding what was asked. – cHao Nov 06 '13 at 06:56
  • @cHao: "What this answer is totally lacking, is any decent answer to that question." If you read the very *first* sentence in my answer: "They are two separate operators because they do two different (albeit related) things." You have your answer. Your reply to that was "well, they shouldn't have the same 'name' then." I've already answered the OP's question in several ways ... you've just been going off about wanting them to have different names ... – Zac Howland Nov 06 '13 at 15:23
  • No, i've been going off about them having the same name and potentially doing two totally different things. It'd make more sense if the pre-vs-post distinction never existed, there was a single "increment" operator, and the compiler generated the right sequence of instructions. As it is, we instead have to write code that does the compiler's job for it. Sure, with the two separate, you *could* make them do different things, or only support pre-increment and not post, or any other such nonsense. But no one does, and no one *should*, because it all violates the hell out of POLA. – cHao Nov 06 '13 at 15:41
  • As it turns out, this same question has been asked on SO before: http://stackoverflow.com/questions/2513227/whether-a-language-needs-preincrement-x-and-postincrement-x – Zac Howland Nov 06 '13 at 15:52
  • Different question. That question asks whether they should exist at all; this one questions why/whether they should ever significantly differ in what they do. – cHao Nov 06 '13 at 15:56
  • But you are making an assumption about *what* they do. The compiler makes no such assumption. Hence the crux of our whole miscommunication here. All the compiler knows is your program is calling a function. It doesn't know that function is similar to another function (that has a different signature) that may be a better match for your intentions because it cannot read your mind. It just knows that you told it to call `func1`. You could have easily told it to call `func2`, but you didn't. – Zac Howland Nov 06 '13 at 16:05
  • I am making an assumption about what they do because the visible difference between `++a` and `a++` is so small. If two things look very similar, humans will subconsciously relate them -- and if the two then act differently without a good reason, cognitive dissonance sets in. "Because they are shorthand for two different functions" is not a reason; it's the very issue. Good answers will include a case where the benefit of that difference outweighs the consistency that would exist if there were one "increment" function/operator and the compiler handled the pre-vs-post part. – cHao Nov 06 '13 at 23:00
  • I couldn't come up with such a case, which is why i was trying to get you to elaborate. Fortunately, [someone else could](http://stackoverflow.com/a/19793875/319403). – cHao Nov 07 '13 at 01:36