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

### 2313. `tuple_size` should always derive from `integral_constant<size_t, N>`

Section: 22.4.7 [tuple.helper] Status: C++14 Submitter: Stephan T. Lavavej Opened: 2013-09-21 Last modified: 2017-07-05

Priority: 2

View all other issues in [tuple.helper].

View all issues with C++14 status.

Discussion:

In 22.4.7 [tuple.helper], the "primary template" is depicted as:

>     template <class... Types>
>     class tuple_size<tuple<Types...> >
>       : public integral_constant<size_t, sizeof...(Types)> { };

However, 22.3.4 [pair.astuple]/1-2 and 24.3.7.7 [array.tuple]/1-2 are underspecified, saying:

>     tuple_size<pair<T1, T2> >::value

> > Returns: Integral constant expression.

> > Value: `2`.

>     tuple_size<array<T, N> >::value

> > Return type: integral constant expression.

> > Value: `N`

They should be required to behave like the "primary template". This is more than a stylistic decision — it allows `tuple_size` to be passed to a function taking `integral_constant`.

LWG 1118 noticed this underspecification, but instead of correcting it, the resolution changed 22.4.7 [tuple.helper]/3 to require `tuple_size<cv T>` to derive from `integral_constant<remove_cv<decltype(TS::value)>::type, TS::value>`. This is unnecessarily overgeneralized. `tuple_size` is primarily for tuples, where it is required to be `size_t`, and it has been extended to handle pairs and arrays, which (as explained above) should also be guaranteed to be `size_t`. `tuple_size<cv T>` works with cv-qualified tuples, pairs, arrays, and user-defined types that also want to participate in the `tuple_size` system. It would be far simpler and perfectly reasonable to expect that user-defined types supporting the "tuple-like protocol" should have `tuple_sizes` of `size_t`.

[Issaquah 2014-02-11: Move to Immediate]

Proposed resolution:

This wording is relative to N3691.

1. Edit 22.3.4 [pair.astuple]/1-2 as indicated:

   >     tuple_size<pair<T1, T2> >::value
   >     template <class T1, class T2>
   >     struct tuple_size<pair<T1, T2>>
   >       : integral_constant<size_t, 2> { };

   > > -1- Returns: Integral constant expression.

   > > -2- Value: `2`.

2. Edit 24.3.7.7 [array.tuple]/1-2 as indicated:

   >     tuple_size<array<T, N> >::value
   >     template <class T, size_t N>
   >     struct tuple_size<array<T, N>>
   >       : integral_constant<size_t, N> { };

   > > -1- Returns: Integral constant expression.

   > > -2- Value: `N`.

3. Edit 22.4.7 [tuple.helper]/p1-p3 as indicated:

   >     template <class T> struct tuple_size;

   > > -?- Remarks: All specializations of `tuple_size<T>` shall meet the `UnaryTypeTrait` requirements (21.3.2 [meta.rqmts]) with a `BaseCharacteristic` of `integral_constant<size_t, N>` for some `N`.

   >     template <class... Types>
   >     struct tuple_size<tuple<Types...> >
   >       : integral_constant<size_t, sizeof...(Types)> { };

   >     template <size_t I, class... Types>
   >     class tuple_element<I, tuple<Types...> > {
   >     public:
   >       typedef TI type;
   >     };

   > > -1- Requires: `I < sizeof...(Types)`. The program is ill-formed if `I` is out of bounds.

   > > […]

   >     template <class T> class tuple_size<const T>;
   >     template <class T> class tuple_size<volatile T>;
   >     template <class T> class tuple_size<const volatile T>;

   > > -3- Let TS denote `tuple_size<T>` of the cv-unqualified type `T`. Then each of the three templates shall meet the `UnaryTypeTrait` requirements (21.3.2 [meta.rqmts]) with a `BaseCharacteristic` of

   > > >     integral_constant<remove_cv<decltype(TS::value)>::typesize_t, TS::value>