Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I tried constructing pairs of integers where the second integer is greater than the first by 1:

1 2
2 3
3 4

Using both std::make_pair and the constructor like so:

std::make_pair(n, n++);

However, this results in the pairs being in reverse:

2 1
3 2
4 3

If I was to put the post-increment on the first parameter or use (n+1) instead, I get the desired result.

Why does it behave this way?

like image 853
Pesho_T Avatar asked May 02 '20 22:05

Pesho_T


1 Answers

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.

like image 54
Yakk - Adam Nevraumont Avatar answered Sep 18 '22 07:09

Yakk - Adam Nevraumont