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::ref
gives usstd::reference_wrapper
rather 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_wrapper
argument 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_wrapper
doesn't have an assignment operator for the referred type. It only has assignment operator for another reference wrapper.std::reference_wrapper
has an implicitly converting constructor that accepts an lvalue, but not one that accepts an rvalue.That is why you can assign
b
which 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.