In the C++11 standard it states that (see cppreference.com, see also section 20.4.2.4 of the standard) it states that
template< class... Types >
tuple<VTypes...> make_tuple( Types&&... args );
Creates a tuple object, deducing the target type from the types of arguments.
For each
Ti
inTypes...
, the corresponding typeVi
inVtypes...
isstd::decay<Ti>::type
unless application ofstd::decay
results instd::reference_wrapper<X>
for some typeX
, in which case the deduced type isX&
.
I am wondering: Why are reference wrappers treated special here?
This is more or less the primary purpose of reference_wrapper
.
Normally, std::make_tuple
always makes tuples of values (std::decay
simulates pass-by-value semantics). Given int x, y; std::make_tuple(x, y);
makes a std::tuple<int, int>
, even though it will have deduced Types
as a pack of references int&, int&
. std::decay
converts those to int, int
.
reference_wrapper
allows you to force creation of tuples of references: std::make_tuple(std::ref(x), y)
will make a std::tuple<int&, int>
.
Other parts of the standard library use reference_wrapper
in the same way. As an example, std::bind
will usually copy/move the bound arguments into the resulting object, but if you want it to store only a reference, you can explicitly request it by passing a reference_wrapper
.
Your title is misleading: using std::reference_wrapper<X>
turns the members to be X&
rather than X
. The reason this transformation is done is that std::reference_wrapper<T>
is an auxiliary type, meant to turn a value type into a reference type. However, the extra conversion needed to make it appear that way sometimes interferes with the usage. Thus, unwrapping the reference where possible seems a reasonable approach: making the std::tuple<...>
member a T&
makes the use more natural.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With