I was trying out the std::reference_wrapper with the following snippet
int a = 42, b = 52;
std::tuple<std::reference_wrapper<int>> t = std::make_tuple(std::ref(a));
std::get<0>(t) = b;
std::cout << "t[0] = " << std::get<0>(t) << ", a = " << a << ", b = " << b
<< std::endl;
The output is t[0] = 52, a = 42, b = 52, which not surprising.
However, if I just use auto for t, namely
int a = 42, b = 52;
auto t = std::make_tuple(std::ref(a));
std::get<0>(t) = b;
std::cout << "t[0] = " << std::get<0>(t) << ", a = " << a << ", b = " << b
<< std::endl;
Then I got t[0] = 52, a = 52, b = 52
Looks like the type becomes int&. Then I have some questions:
- I thought
std::refgives usstd::reference_wrapperrather than&? - How I should explain the case of
&and why it is different fromstd::reference_wrapper. - I also noticed that, in the case of
std::reference_wrapper,std::get<0>(t) = 52;does not compile. (While in the case of&it does). the error is "calling a private constructor of class 'std::__1::reference_wrapper'". Could someone explain that in more detail?
Thanks!!
That's not a question, but you thought correctly.
When a
std::reference_wrapperargument passed tostd::make_tuple, the resulting tuple will have a reference member rather than a reference wrapper.The difference in behaviour is because when you assign a reference, you modify the referred object while when you assign a reference wrapper, you instead rebind the wrapper to refer to another object and don't modify the referred object.
std::reference_wrapperdoesn't have an assignment operator for the referred type. It only has assignment operator for another reference wrapper.std::reference_wrapperhas an implicitly converting constructor that accepts an lvalue, but not one that accepts an rvalue.That is why you can assign
bwhich is an lvalue, but cannot assign 52 which is a prvalue. This is a good thing because the lifetime of the temporary object cannot be extended by the reference wrapper.