This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of Resolved status.

### 1201. Do we always want to unwrap `ref`-wrappers in `make_tuple`

Section: 20.5.4 [tuple.creation], 20.4 [pairs] Status: Resolved Submitter: Alisdair Meredith Opened: 2009-09-05 Last modified: 2018-10-05

Priority: Not Prioritized

View all other issues in [tuple.creation].

View all issues with Resolved status.

Discussion:

Spotting a recent thread on the boost lists regarding collapsing optional representations in `optional<optional<T>>` instances, I wonder if we have some of the same issues with `make_tuple`, and now `make_pair`?

Essentially, if my generic code in my own library is handed a `reference_wrapper` by a user, and my library in turn delegates some logic to `make_pair` or `make_tuple`, then I am going to end up with a `pair`/`tuple` holding a real reference rather than the intended reference wrapper.

There are two things as a library author I can do at this point:

1. document my library also has the same reference-wrapper behaviour as `std::make_tuple`
2. roll my own `make_tuple` that does not unwrap rereferences, a lost opportunity to re-use the standard library.

(There may be some metaprogramming approaches my library can use to wrap the `make_tuple` call, but all will be significantly more complex than simply implementing a simplified `make_tuple`.)

Now I don't propose we lose this library facility, I think unwrapping references will be the common behaviour. However, we might want to consider adding another overload that does nothing special with `ref`-wrappers. Note that we already have a second overload of `make_tuple` in the library, called `tie`.

[ 2009-09-30 Daniel adds: ]

> I suggest to change the currently proposed paragraph for `make_simple_pair`

> >     template<typename... Types>
> >       pair<typename decay<Types>::type...> make_simple_pair(Types&&... t);

> > > Type requirements: `sizeof...(Types) == 2`. Remarks: The program shall be ill-formed, if `sizeof...(Types) != 2`.

> > > ...

> or alternatively (but with a slightly different semantic):

> > > Remarks: If `sizeof...(Types) != 2`, this function shall not participate in overload resolution.

> to follow a currently introduced style and because the library does not have yet a specific "Type requirements" element. If such thing would be considered as useful this should be done as a separate issue. Given the increasing complexity of either of these wordings it might be preferable to use the normal two-argument-declaration style again in either of the following ways:

> 1.     template<class T1, class T2>
>        pair<typename decay<T1>::type, typename decay<T2>::type>
>        make_simple_pair(T1&& t1, T2&& t2);

> 2.     template<class T1, class T2>
>        pair<V1, V2> make_simple_pair(T1&& t1, T2&& t2);

>    > Let `V1` be `typename decay<T1>::type` and `V2` be `typename decay<T2>::type`.

[ 2009-10 post-Santa Cruz: ]

> Mark as Tentatively NAD Future.

[2018-10-05 Status to Resolved]

Alisdair notes that this is solved by CTAD that was added in C++17

Rationale:

Does not have sufficient support at this time. May wish to reconsider for a future standard.

Proposed resolution:

Add the following function to 20.4 [pairs] and signature in appropriate synopses:

>     template<typename... Types>
>       pair<typename decay<Types>::type...> make_simple_pair(Types&&... t);

> > Type requirements: `sizeof...(Types) == 2`.

> > Returns: `pair<typename decay<Types>::type...>(std::forward<Types>(t)...)`.

[ Draughting note: I chose a variadic representation similar to `make_tuple` rather than naming both types as it is easier to read through the clutter of metaprogramming this way. Given there are exactly two elements, the committee may prefer to draught with two explicit template type parameters instead ]

Add the following function to 20.5.4 [tuple.creation] and signature in appropriate synopses:

>     template<typename... Types>
>       tuple<typename decay<Types>::type...> make_simple_tuple(Types&&... t);

> > Returns: `tuple<typename decay<Types>::type...>(std::forward<Types>(t)...)`.