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.
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> >::valueReturns: Integral constant expression.
Value: 2.
tuple_size<array<T, N> >::valueReturn 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<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.[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> >::valuetemplate <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> >::valuetemplate <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 of
integral_constant<remove_cv<decltype(TS::value)>::typesize_t, TS::value>