Constructing std::pair of integers with a variable using post-increment

This has to do with the order of evaluation. From cppreference.com

Order of evaluation of any part of any expression, including order of evaluation of function arguments is unspecified. The compiler can evaluate operands and other subexpressions in any order, and may choose another order when the same expression is evaluated again.

Therefore, one can not guarantee whether n or n++ evaluates first.


From cppreference:

When calling a function (whether or not the function is inline, and whether or not explicit function call syntax is used), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function.

So what is going on here is this.

int n = 0;
auto p = std::make_pair( n, n++ );

First we determine the overload of make_pair; we get:

make_pair<int&, int>( int&, int&& )

ie, the first argument is a rvalue reference (which ends up binding to n), the second in an lvalue reference (which ends up binding to the temporary that n++ returns).

We evaluate the arguments of make_pair. They are sequenced in an arbitrary manner, but you'll see it doesn't matter here.

Binding n to int& doesn't copy a value, it just stores a reference.

Binding n++ to int&& creates a temporary object, copies the value of n into it, then sets up a side effect to increase n afterwards.

When the side effect happens is the key here. As noted above, it has to happen sometime before the function make_pair is called.

It could happen before n is evaluated for the first argument, or after; it doesn't matter, because we are binding a reference to n to the argument. It is, however, evaluated before we do the body of make_pair.

So within make_pair, it is guaranteed to have a reference to n, whose value is 1, and a reference to a temporary whose value is 0. It then runs and returns a pair with those values.


It appears you misunderstood what n++ means -- it means "return the value of n, then afterwards increase it", it does not mean "return a value 1 bigger than n".

The way you return a value 1 bigger than n is n+1.