1118. tuple query APIs do not support cv-qualification

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 tuples, pairs or arrays.

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 pairs/arrays 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 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...> >;
    
  2. 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<TE::type>::type, and
    • for the third specialization, the type add_cv<TE::type>::type