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.
pair and tupleSection: 22.3.2 [pairs.pair], 22.4.4.2 [tuple.cnstr] Status: Resolved Submitter: Daniel Krügler Opened: 2010-03-20 Last modified: 2016-01-28
Priority: Not Prioritized
View other active issues in [pairs.pair].
View all other issues in [pairs.pair].
View all issues with Resolved status.
Discussion:
In analogy to library defect 811(i), tuple's variadic constructor
template <class... UTypes> explicit tuple(UTypes&&... u);
creates the same problem as pair:
#include <tuple>
int main()
{
std::tuple<char*> p(0);
}
produces a similar compile error for a recent gcc implementation.
I suggest to follow the same resolution path as has been applied to
pair's corresponding c'tor, that is require that these c'tors should
not participate in overload resolution, if the arguments are not implicitly
convertible to the element types.
Further-on both pair and tuple provide converting constructors
from different pairs/tuples that should be not available, if
the corresponding element types are not implicitly convertible. It seems
astonishing that in the following example
struct A {
explicit A(int);
};
A a = 1; // Error
std::tuple<A> ta = std::make_tuple(1); // # OK?
the initialization marked with # could be well-formed.
[ Only constraints on constructors are suggested. Adding similar constraints on assignment operators is considered as QoI, because the assigments wouldn't be well-formed anyway. ]
Following 22.3.2 [pairs.pair]/5 add a new Remarks element:
template<class U, class V> pair(const pair<U, V>& p);5 Effects: Initializes members from the corresponding members of the argument
, performing implicit conversions as needed.Remarks: This constructor shall not participate in overload resolution unless
Uis implicitly convertible tofirst_typeandVis implicitly convertible tosecond_type.
Following 22.3.2 [pairs.pair]/6 add a new Remarks element:
template<class U, class V> pair(pair<U, V>&& p);6 Effects: The constructor initializes
firstwithstd::move(p.first)and second withstd::move(p.second).Remarks: This constructor shall not participate in overload resolution unless
Uis implicitly convertible tofirst_typeandVis implicitly convertible tosecond_type.
Following 22.4.4.2 [tuple.cnstr]/7 add a new Remarks element:
template <class... UTypes> explicit tuple(UTypes&&... u);6 Requires: Each type in
Typesshall satisfy the requirements ofMoveConstructible(Table 33) from the corresponding type inUTypes.sizeof...(Types) == sizeof...(UTypes).7 Effects: Initializes the elements in the
tuplewith the corresponding value instd::forward<UTypes>(u).Remarks: This constructor shall not participate in overload resolution unless each type in
UTypesis implicitly convertible to its corresponding type inTypes.
Following 22.4.4.2 [tuple.cnstr]/13 add a new Remarks element:
template <class... UTypes> tuple(const tuple<UTypes...>& u);12 Requires: Each type in
Typesshall be constructible from the corresponding type inUTypes.sizeof...(Types) == sizeof...(UTypes).13 Effects: Constructs each element of
*thiswith the corresponding element ofu.Remarks: This constructor shall not participate in overload resolution unless each type in
UTypesis implicitly convertible to its corresponding type inTypes.14 [Note:
enable_ifcan be used to make the converting constructor and assignment operator exist only in the cases where the source and target have the same number of elements. — end note]
Following 22.4.4.2 [tuple.cnstr]/16 add a new Remarks element:
template <class... UTypes> tuple(tuple<UTypes...>&& u);15 Requires: Each type in
Typesshall shall satisfy the requirements ofMoveConstructible(Table 33) from the corresponding type inUTypes.sizeof...(Types) == sizeof...(UTypes).16 Effects: Move-constructs each element of
*thiswith the corresponding element ofu.Remarks: This constructor shall not participate in overload resolution unless each type in
UTypesis implicitly convertible to its corresponding type inTypes.[Note:
enable_ifcan be used to make the converting constructor and assignment operator exist only in the cases where the source and target have the same number of elements. — end note]
Following 22.4.4.2 [tuple.cnstr]/18 add a new Remarks element:
template <class U1, class U2> tuple(const pair<U1, U2>& u);17 Requires: The first type in
Typesshall be constructible fromU1and the second type inTypesshall be constructible fromU2.sizeof...(Types) == 2.18 Effects: Constructs the first element with
u.firstand the second element withu.second.Remarks: This constructor shall not participate in overload resolution unless
U1is implicitly convertible to the first type inTypesandU2is implicitly convertible to the second type inTypes.
Following 22.4.4.2 [tuple.cnstr]/20 add a new Remarks element:
template <class U1, class U2> tuple(pair<U1, U2>&& u);19 Requires: The first type in
Typesshall shall satisfy the requirements ofMoveConstructible(Table 33) fromU1and the second type inTypesshall be move-constructible fromU2.sizeof...(Types) == 2.20 Effects: Constructs the first element with
std::move(u.first)and the second element withstd::move(u.second)Remarks: This constructor shall not participate in overload resolution unless
U1is implicitly convertible to the first type inTypesandU2is implicitly convertible to the second type inTypes.
[ 2010-10-24 Daniel adds: ]
Accepting n3140 would solve this issue.
Proposed resolution:
See n3140.