4
#include<iostream>
#include<utility>
#include<tuple>
#include<functional>
using namespace std;
int main()
{
    int i = 0;
    auto p = make_pair(ref(i), ref(i++));
    p.first++;
    p.second++;
    cout << "i = " << i << endl;
}

For example if I use ref() like this, the compiler will say

use of deleted function 'void std::ref(const _Tp&&) [with _Tp = int]'

however if my code is following

#include<iostream>
#include<utility>
#include<tuple>
#include<functional>
using namespace std;
int main()
{
    int i = 0;
    auto p = make_pair(ref(i), ref(++i));
    p.first++;
    p.second++;
    cout << "i = " << i << endl;
}

I will successfully get the output i = 3, so I can't understand why I get so different answers.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
Yyh
  • 59
  • 1
  • 8

1 Answers1

11

std::ref takes a variable and gives you something that acts like a reference to that variable.

i++ is not a variable; it is a temporary. That's because of how post-increment works; the original value is incremented but the expression evaluates to the old value, and a temporary is required to hold that old value so you can read it.

std::ref doesn't allow you to use a temporary, in order to avoid mistakes like this one. It would be a dangling reference, otherwise.

++i, on the other hand, just gives you back the original variable, so you can take a reference to that just fine.

However, you can't put i and ++i right next to each other like that; the two expressions are indeterminately sequenced (or something) with respect to each other. Avoid this kind of code at all costs.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 2
    I looked up the sequencing, in C++14 it was UB due to unsequenced argument side-effects, but in C++17 it will be indeterminately sequenced, i.e. the `ref(i)` may read `i` either before or after the side-effect of `++i` is complete, but it is not UB. The latter text is in as of N4606. [Reference](http://stackoverflow.com/a/39238441/1505939) – M.M Feb 24 '17 at 12:25
  • I'm not sure that *this particular case* is UB, as the value of i is not used in the sub-expression of taking a reference to it. The general point is correct however – Caleth Feb 24 '17 at 12:34
  • This problem also happens when you say vector myvec{1,2,3}; ref(myvec[0]). You will get: error: use of deleted function ‘void std::ref(const _Tp&&) – Kemin Zhou Dec 03 '17 at 06:31