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

### 1385. `tuple_cat` should be a single variadic signature

Section: 20.5.4 [tuple.creation] Status: C++11 Submitter: BSI Opened: 2010-08-25 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [tuple.creation].

View all issues with C++11 status.

Discussion:

Addresses GB-88

The `tuple_cat` template consists of four overloads and that can concatenate only two `tuple`s. A single variadic signature that can concatenate an arbitrary number of `tuple`s would be preferred.

[ Resolution proposed by ballot comment: ]

> Adopt a simplified form of the proposal in n2975, restricted to `tuple`s and neither requiring nor outlawing support for other `tuple`-like types.

[ 2010 Rapperswil: Alisdair to provide wording. ]

[ 2010-11-06: Daniel comments and proposes some alternative wording: ]

There are some problems in the wording: First, even though the result type `tuple<see below>` implies it, the specification of the contained tuple element types is missing. Second, the term "`tuple` protocol" is not defined anywhere and I see no reason why this normative wording should not be a non-normative note. We could at least give a better approximation, maybe "tuple-like protocol" as indicated from header `<utility>` synopsis. Further, it seems to me that the effects need to contain a combination of `std::forward` with the call of `get`. Finally I suggest to replace the requirements `Move/CopyConstructible` by proper usage of `is_constructible`, as indicated by n3140.

[ 2010 Batavia ]

Moved to Ready with Daniel's improved wording.

Proposed resolution:

Note: This alternate proposed resolution works only if 1191 has been accepted.

1. Change 20.5.1 [tuple.general] p. 2, header `<tuple>` synopsis, as indicated:

   >     namespace std {

   >     ...

   >     // 20.4.2.4, tuple creation functions:
   >     const unspecified ignore;

   >     template <class... Types>
   >       tuple<VTypes...> make_tuple(Types&&...);
   >       template <class... Types>
   >       tuple<ATypes...> forward_as_tuple(Types&&...);

   >     template<class... Types>
   >       tuple<Types&...> tie(Types&...);

   >     template <class... TTypes, class... UTypes>
   >       tuple<TTypes..., UTypes...> tuple_cat(const tuple<TTypes...>&, const tuple<UTypes...>&);
   >     template <class... TTypes, class... UTypes>
   >       tuple<TTypes..., UTypes...> tuple_cat(tuple<TTypes...>&&, const tuple<UTypes...>&);
   >     template <class... TTypes, class... UTypes>
   >       tuple<TTypes..., UTypes...> tuple_cat(const tuple<TTypes...>&, tuple<UTypes...>&&);
   >     template <class... TTypes, class... UTypes>
   >       tuple<TTypes..., UTypes...> tuple_cat(tuple<TTypes...>&&, tuple<UTypes...>&&);
   >     template <class... Tuples>
   >       tuple<CTypes...> tuple_cat(Tuples&&...);

   >     ...

2. Change 20.5.4 [tuple.creation] as indicated:

   >     template <class... TTypes, class... UTypes>
   >       tuple<TTypes..., UTypes...> tuple_cat(const tuple<TTypes...>& t, const tuple<UTypes...>& u);

   > > 8 Requires: All the types in `TTypes` shall be `CopyConstructible` (Table 35). All the types in `UTypes` shall be `CopyConstructible` (Table 35).

   > > 9 Returns: A `tuple` object constructed by copy constructing its first `sizeof...(TTypes)` elements from the corresponding elements of `t` and copy constructing its last `sizeof...(UTypes)` elements from the corresponding elements of `u`.

   >     template <class... TTypes, class... UTypes>
   >       tuple<TTypes..., UTypes...> tuple_cat(tuple<TTypes...>&& t, const tuple<UTypes...>& u);

   > > 10 Requires: All the types in `TTypes` shall be `MoveConstructible` (Table 34). All the types in `UTypes` shall be `CopyConstructible` (Table 35).

   > > 11 Returns: A `tuple` object constructed by move constructing its first `sizeof...(TTypes)` elements from the corresponding elements of `t` and copy constructing its last `sizeof...(UTypes)` elements from the corresponding elements of `u`.

   >     template <class... TTypes, class... UTypes>
   >       tuple<TTypes..., UTypes...> tuple_cat(const tuple<TTypes...>& t, tuple<UTypes...>&& u);

   > > 12 Requires: All the types in `TTypes` shall be `CopyConstructible` (Table 35). All the types in `UTypes` shall be `MoveConstructible` (Table 34).

   > > 13 Returns: A `tuple` object constructed by copy constructing its first `sizeof...(TTypes)` elements from the corresponding elements of `t` and move constructing its last `sizeof...(UTypes)` elements from the corresponding elements of `u`.

   >     template <class... TTypes, class... UTypes>
   >       tuple<TTypes..., UTypes...> tuple_cat(tuple<TTypes...>&& t, tuple<UTypes...>&& u);

   > > 14 Requires: All the types in `TTypes` shall be `MoveConstructible` (Table 34). All the types in `UTypes` shall be `MoveConstructible` (Table 34).

   > > 15 Returns: A `tuple` object constructed by move constructing its first `sizeof...(TTypes)` elements from the corresponding elements of `t` and move constructing its last `sizeof...(UTypes)` elements from the corresponding elements of `u`.

   >     template <class... Tuples>
   >       tuple<CTypes...> tuple_cat(Tuples&&... tpls);

   > > 8 Let `Ti` be the `i`th type in `Tuples`, `Ui` be `remove_reference<Ti>::type`, and `tpi` be the `i`th parameter in the function parameter pack `tpls`, where all indexing is zero-based in the following paragraphs of this sub-clause [tuple.creation].

   > > 9 Requires: For all `i`, `Ui` shall be the type cv`i` `tuple<Argsi...>`, where cv`i` is the (possibly empty) `i`th cv-qualifier-seq, and `Argsi` is the parameter pack representing the element types in `Ui`. Let `Aik` be the `ki`th type in `Argsi`, then for all `Aik` the following requirements shall be satisfied: If `Ti` is deduced as an lvalue reference type, then `is_constructible<Aik, cvi Aik&>::value == true`, otherwise `is_constructible<Aik, cvi Aik&&>::value == true`.

   > > 10 Remarks: The types in `CTypes` shall be equal to the ordered sequence of the expanded types `Args0..., Args1..., Argsn-1...`, where `n` equals `sizeof...(Tuples)`. Let `ei...` be the `i`th ordered sequence of tuple elements of the result `tuple` object corresponding to the type sequence `Argsi`.

   > > 11 Returns: A `tuple` object constructed by initializing the `ki`th type element `eik` in `ei...` with `get<ki>(std::forward<Ti>(tpi))` for each valid `ki` and each element group `ei` in order.

   > > 12 [Note: An implementation may support additional types in the parameter pack `Tuples`, such as `pair` and `array` that support the `tuple`-like protocol. — end note]