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.

### 1118. `tuple` query APIs do not support cv-qualification

Section: 20.5.6 [tuple.helper] Status: C++11 Submitter: Alisdair Meredith Opened: 2009-05-23 Last modified: 2016-01-28

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_size` templates 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_element` partial 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:

1. Change 20.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...> >;

2. Add the end of subclause 20.5.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<TE::type>::type`, and
   > > - for the third specialization, the type `add_cv<TE::type>::type`