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.

### 1324. Still too many implicit conversions for `pair` and `tuple`

Section: 20.4.2 [pairs.pair], 20.5.3.1 [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, `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. ]

1. Following 20.4.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 `U` is implicitly convertible to `first_type` and `V` is implicitly convertible to `second_type`.

2. Following 20.4.2 [pairs.pair]/6 add a new Remarks element:

   >     template<class U, class V> pair(pair<U, V>&& p);

   > > 6 Effects: The constructor initializes `first` with `std::move(p.first)` and second with `std::move(p.second)`.

   > > Remarks: This constructor shall not participate in overload resolution unless `U` is implicitly convertible to `first_type` and `V` is implicitly convertible to `second_type`.

3. Following 20.5.3.1 [tuple.cnstr]/7 add a new Remarks element:

   >     template <class... UTypes>
   >     explicit tuple(UTypes&&... u);

   > > 6 Requires: Each type in `Types` shall satisfy the requirements of `MoveConstructible` (Table 33) from the corresponding type in `UTypes`. `sizeof...(Types) == sizeof...(UTypes)`.

   > > 7 Effects: Initializes the elements in the `tuple` with the corresponding value in `std::forward<UTypes>(u)`.

   > > Remarks: This constructor shall not participate in overload resolution unless each type in `UTypes` is implicitly convertible to its corresponding type in `Types`.

4. Following 20.5.3.1 [tuple.cnstr]/13 add a new Remarks element:

   >     template <class... UTypes> tuple(const tuple<UTypes...>& u);

   > > 12 Requires: Each type in `Types` shall be constructible from the corresponding type in `UTypes`. `sizeof...(Types) == sizeof...(UTypes)`.

   > > 13 Effects: Constructs each element of `*this` with the corresponding element of `u`.

   > > Remarks: This constructor shall not participate in overload resolution unless each type in `UTypes` is implicitly convertible to its corresponding type in `Types`.

   > > 14 [Note: `enable_if` can 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]

5. Following 20.5.3.1 [tuple.cnstr]/16 add a new Remarks element:

   >     template <class... UTypes> tuple(tuple<UTypes...>&& u);

   > > 15 Requires: Each type in `Types` shall shall satisfy the requirements of `MoveConstructible` (Table 33) from the corresponding type in `UTypes`. `sizeof...(Types) == sizeof...(UTypes)`.

   > > 16 Effects: Move-constructs each element of `*this` with the corresponding element of `u`.

   > > Remarks: This constructor shall not participate in overload resolution unless each type in `UTypes` is implicitly convertible to its corresponding type in `Types`.

   > > [Note: `enable_if` can 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]

6. Following 20.5.3.1 [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 `Types` shall be constructible from `U1` and the second type in `Types` shall be constructible from `U2`. `sizeof...(Types) == 2`.

   > > 18 Effects: Constructs the first element with `u.first` and the second element with `u.second`.

   > > Remarks: This constructor shall not participate in overload resolution unless `U1` is implicitly convertible to the first type in `Types` and `U2` is implicitly convertible to the second type in `Types`.

7. Following 20.5.3.1 [tuple.cnstr]/20 add a new Remarks element:

   >     template <class U1, class U2> tuple(pair<U1, U2>&& u);

   > > 19 Requires: The first type in `Types` shall shall satisfy the requirements of `MoveConstructible`(Table 33) from `U1` and the second type in `Types` shall be move-constructible from `U2`. `sizeof...(Types) == 2`.

   > > 20 Effects: Constructs the first element with `std::move(u.first)` and the second element with `std::move(u.second)`

   > > Remarks: This constructor shall not participate in overload resolution unless `U1` is implicitly convertible to the first type in `Types` and `U2` is implicitly convertible to the second type in `Types`.

[ 2010-10-24 Daniel adds: ]

> Accepting n3140 would solve this issue.

Proposed resolution:

See n3140.