*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.*

`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<`

to derive from
*cv* T>`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<`

works with *cv* T>*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.

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`

.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`

.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`

ofintegral_constant<

~~remove_cv<decltype(TS::value)>::type~~size_t, TS::value>