ref
-wrappers in make_tuple
Section: 22.4.5 [tuple.creation], 22.3 [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:
std::make_tuple
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:Remarks: The program shall be ill-formed, ifsizeof...(Types) == 2
.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:
template<class T1, class T2> pair<typename decay<T1>::type, typename decay<T2>::type> make_simple_pair(T1&& t1, T2&& t2); template<class T1, class T2> pair<V1, V2> make_simple_pair(T1&& t1, T2&& t2);Let
V1
betypename decay<T1>::type
andV2
betypename 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 22.3 [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 22.4.5 [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)...)
.