Title
tuple_size should always derive from integral_constant<size_t, N>
Status
c++14
Section
[tuple.helper]
Submitter
Stephan T. Lavavej

Created on 2013-09-21.00:00:00 last changed 123 months ago

Messages

Date: 2014-02-13.04:55:14

Proposed resolution:

This wording is relative to N3691.

  1. Edit [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 [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 [tuple.helper]/p1-p3 as indicated:

    template <class T> struct tuple_size;
    

    -?- Remarks: All specializations of tuple_size<T> shall meet the UnaryTypeTrait requirements ([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 ([meta.rqmts]) with a BaseCharacteristic of

    integral_constant<remove_cv<decltype(TS::value)>::typesize_t, TS::value>
    
Date: 2014-02-13.04:55:14

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

Date: 2013-10-11.17:04:39

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

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

However, [pair.astuple]/1-2 and [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 [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.

History
Date User Action Args
2014-02-27 17:03:20adminsetstatus: wp -> c++14
2014-02-20 13:52:38adminsetstatus: immediate -> wp
2014-02-13 04:55:14adminsetmessages: + msg6824
2014-02-13 04:55:14adminsetstatus: new -> immediate
2013-10-10 22:04:40adminsetmessages: + msg6695
2013-09-21 00:00:00admincreate