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`.
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.
[ 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.
Ouch, alright, that's unfortunate. Is libcxx actually defining std::tuple_size differently, in different places?
It appears that libc++ is consistent; it uses 'class' everywhere.
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.
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).