**Section:** 23.5.3.6 [tuple.helper] **Status:** C++11
**Submitter:** Alisdair Meredith **Opened:** 2009-05-23 **Last modified:** 2016-02-10

**Priority: **Not Prioritized

**View all other** issues in [tuple.helper].

**View all issues with** C++11 status.

**Discussion:**

The APIs `tuple_size` and `tuple_element` do not support
cv-qualified `tuple`s, `pair`s or `array`s.

The most generic solution would be to supply partial specializations once
for each cv-type in the `tuple` header. However, requiring this header for
cv-qualified `pair`s/`array`s seems unhelpful. The BSI editorial
suggestion (UK-198/US-69,
N2533)
to merge `tuple` into `<utility>` would help with `pair`,
but not `array`. That might be resolved by making a dependency between the
`<array>` header and `<utility>`, or simply recognising
the dependency be fulfilled in a Remark.

*[
2009-05-24 Daniel adds:
]*

All

tuple_sizetemplates with a base class need to derive publicly, e.g.template <IdentityOf T> class tuple_size< const T > : public tuple_size<T> {};The same applies to the tuple_element class hierarchies.

What is actually meant with the comment

this solution relies on 'metafunction forwarding' to inherit the nested typename type

?

I ask, because all base classes are currently unconstrained and their instantiation is invalid in the constrained context of the

tuple_elementpartial template specializations.

*[
2009-05-24 Alisdair adds:
]*

I think a better solution might be to ask Pete editorially to change all declarations of tupling APIs to use the struct specifier instead of class.

"metafunction forwarding" refers to the MPL metafunction protocol, where a metafunction result is declared as a nested typedef with the name "type", allowing metafunctions to be chained by means of inheritance. It is a neater syntax than repeatedly declaring a typedef, and inheritance syntax is slightly nicer when it comes to additional typename keywords.

The constrained template with an unconstrained base is a good observation though.

*[
2009-10 post-Santa Cruz:
]*

Move to Open, Alisdair to provide wording. Once wording is provided, Howard will move to Review.

*[
2010-03-28 Daniel deconceptified wording.
]*

*[
Post-Rapperswil - Daniel provides wording:
]*

The below given P/R reflects the discussion from the Rapperswil meeting that the wording should not constrain implementation freedom to realize the actual issue target. Thus the original code form was replaced by normative words.

While preparing this wording it turned out that several `tuple_size` specializations as
that of `pair` and `array` are underspecified, because the underlying type of the member
value is not specified except that it is an integral type. For the specializations we could introduce a
canonical one - like `size_t` - or we could use the same type as the specialization of the
unqualified type uses. The following wording follows the second approach.

The wording refers to N3126.

Moved to Tentatively Ready after 6 positive votes on c++std-lib.

*[
Adopted at 2010-11 Batavia
]*

**Proposed resolution:**

- Change 23.5.1 [tuple.general] p.2, header
`<tuple>`synopsis, as indicated:// 20.4.2.5, tuple helper classes: template <class T> class tuple_size; // undefined 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>; template <class... Types> class tuple_size<tuple<Types...> >; template <size_t I, class T> class tuple_element; // undefined template <size_t I, class T> class tuple_element<I, const T>; template <size_t I, class T> class tuple_element<I, volatile T>; template <size_t I, class T> class tuple_element<I, const volatile T>; template <size_t I, class... Types> class tuple_element<I, tuple<Types...> >;

- Add the end of subclause 23.5.3.6 [tuple.helper] insert the following two paragraphs:
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>;

Let

*TS*denote`tuple_size<T>`of the*cv*-unqualified type`T`. Then each of the three templates shall meet the UnaryTypeTrait requirements (20.7.1) with a BaseCharacteristic of`integral_constant<remove_cv<decltype(`.*TS*::value)>::type,*TS*::value>template <size_t I, class T> class tuple_element<I, const T>; template <size_t I, class T> class tuple_element<I, volatile T>; template <size_t I, class T> class tuple_element<I, const volatile T>;

Let

*TE*denote`tuple_element<I, T>`of the*cv*-unqualified type`T`. Then each of the three templates shall meet the TransformationTrait requirements (20.7.1) with a member typedef`type`that shall name the same type as the following type:- for the first specialization, the type
`add_const<`,*TE*::type>::type - for the second specialization, the type
`add_volatile<`, and*TE*::type>::type - for the third specialization, the type
`add_cv<`*TE*::type>::type

- for the first specialization, the type