LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 39871 - std::tuple_size should be a struct
Summary: std::tuple_size should be a struct
Status: RESOLVED FIXED
Alias: None
Product: libc++
Classification: Unclassified
Component: All Bugs (show other bugs)
Version: unspecified
Hardware: PC All
: P enhancement
Assignee: Marshall Clow (home)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2018-12-03 10:08 PST by Arvid Gerstmann
Modified: 2019-01-11 15:19 PST (History)
3 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Arvid Gerstmann 2018-12-03 10:08:36 PST
Currently `std::tuple_size` is declared as `class tuple_size`. According to the C++ standard, `tuple_size` is a `struct` (http://eel.is/c++draft/tuple.helper#lib:tuple_size). 

This creates portability problems between libcxx and libstdc++, which correctly declares it as a `struct`. Currently using either will result in `-Wmismatched-tags`.
Comment 1 Arvid Gerstmann 2018-12-03 10:18:43 PST
Further research revealed this might've changed recently? The C++14 draft I have access to (N3936, Page 491) lists them as `class` , same as the C++11 draft (N3337, Page 473). 

Since the only ABI difference will be on MSVC, and MSVC is using `struct`, I think it could be possible to change it to a `struct`. Which will possibly break programs compiled against an old version of libcxx on Windows, but will provide ABI compatibility with MSVC in the future.
Comment 2 Marshall Clow (home) 2018-12-03 14:58:45 PST
[ Short answer, it's not libc++, it's the standard ]

In [utility.syn], we've got (this is all post-2017):

// 19.4.4, tuple-like access to pair
template<class T> class tuple_size;
template<size_t I, class T> class tuple_element;
template<class T1, class T2> struct tuple_size<pair<T1, T2>>;
template<size_t I, class T1, class T2> struct tuple_element<I, pair<T1, T2>>;

In [pair.astuple]:
template<class T1, class T2>
  struct tuple_size<pair<T1, T2>> : integral_constant<size_t, 2> {};

In [tuple.syn]
// 19.5.3.6, tuple helper classes
template<class T> class tuple_size;
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...>>;

and in [tuple.helper]:

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

In [array.syn]:
template<class T> class tuple_size;
template<size_t I, class T> class tuple_element;

template<class T, size_t N>
  struct tuple_size<array<T, N>>;
template<size_t I, class T, size_t N>
  struct tuple_element<I, array<T, N>>;

in [array.tuple]:
template<class T, size_t N>
  struct tuple_size<array<T, N>> : integral_constant<size_t, N> { };
tuple_element<I, array<T, N>>::type;

I'll have to clean this up in the standard.
Comment 3 Arvid Gerstmann 2018-12-06 23:11:45 PST
Ouch, alright, that's unfortunate. 
Is libcxx actually defining std::tuple_size differently, in different places?
Comment 4 Marshall Clow (home) 2018-12-07 08:42:48 PST
It appears that libc++ is consistent; it uses 'class' everywhere.
Comment 5 Marshall Clow (home) 2019-01-11 14:00:03 PST
The standard isn't going to change; see https://github.com/cplusplus/draft/issues/534

Committed revision 350972 to make `tuple_size` a struct everywhere.
Comment 6 Richard Smith 2019-01-11 15:19:54 PST
As of r348233, Clang ignores declarations in system headers when deciding whether to issue -Wmismatched-tags, which should cover this more generally (but only for new versions of Clang, of course).