Author: ericwf Date: Mon Jan 2 17:54:13 2017 New Revision: 290846 URL: http://llvm.org/viewvc/llvm-project?rev=290846&view=rev Log: Re-implement LWG 2770 - Fix tuple_size with structured bindings.
This patch implements the correct PR for LWG 2770. It also makes the primary tuple_size template incomplete again which fixes part of llvm.org/PR31513. Modified: libcxx/trunk/include/__tuple libcxx/trunk/include/tuple libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.fail.cpp libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.pass.cpp libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_v.fail.cpp Modified: libcxx/trunk/include/__tuple URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__tuple?rev=290846&r1=290845&r2=290846&view=diff ============================================================================== --- libcxx/trunk/include/__tuple (original) +++ libcxx/trunk/include/__tuple Mon Jan 2 17:54:13 2017 @@ -22,19 +22,32 @@ _LIBCPP_BEGIN_NAMESPACE_STD -template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_size {}; +template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_size; + +struct __empty_tuple_size_base {}; + +template <class _Tp, class = void> +struct __tuple_size_base_type { + typedef __empty_tuple_size_base type; +}; + +template <class _Tp> +struct __tuple_size_base_type<_Tp, typename __void_t<decltype(tuple_size<_Tp>::value)>::type> +{ + typedef integral_constant<size_t, tuple_size<_Tp>::value> type; +}; template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_size<const _Tp> - : public tuple_size<_Tp> {}; + : public __tuple_size_base_type<_Tp>::type {}; template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_size<volatile _Tp> - : public tuple_size<_Tp> {}; + : public __tuple_size_base_type<_Tp>::type {}; template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_size<const volatile _Tp> - : public tuple_size<_Tp> {}; + : public __tuple_size_base_type<_Tp>::type {}; template <size_t _Ip, class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_element; Modified: libcxx/trunk/include/tuple URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/tuple?rev=290846&r1=290845&r2=290846&view=diff ============================================================================== --- libcxx/trunk/include/tuple (original) +++ libcxx/trunk/include/tuple Mon Jan 2 17:54:13 2017 @@ -84,7 +84,7 @@ template <class T, class Tuple> constexpr T make_from_tuple(Tuple&& t); // C++17 // 20.4.1.4, tuple helper classes: -template <class T> class tuple_size; +template <class T> class tuple_size; // undefined template <class... T> class tuple_size<tuple<T...>>; template <class T> constexpr size_t tuple_size_v = tuple_size<T>::value; // C++17 Modified: libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.fail.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.fail.cpp?rev=290846&r1=290845&r2=290846&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.fail.cpp (original) +++ libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.fail.cpp Mon Jan 2 17:54:13 2017 @@ -21,7 +21,7 @@ int main() { - (void)std::tuple_size<std::tuple<> &>::value; // expected-error {{no member named 'value'}} - (void)std::tuple_size<int>::value; // expected-error {{no member named 'value'}} - (void)std::tuple_size<std::tuple<>*>::value; // expected-error {{no member named 'value'}} + (void)std::tuple_size<std::tuple<> &>::value; // expected-error {{implicit instantiation of undefined template}} + (void)std::tuple_size<int>::value; // expected-error {{implicit instantiation of undefined template}} + (void)std::tuple_size<std::tuple<>*>::value; // expected-error {{implicit instantiation of undefined template}} } Modified: libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.pass.cpp?rev=290846&r1=290845&r2=290846&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size.pass.cpp Mon Jan 2 17:54:13 2017 @@ -18,8 +18,6 @@ // UNSUPPORTED: c++98, c++03 #include <tuple> -#include <utility> -#include <array> #include <type_traits> template <class T, class = decltype(std::tuple_size<T>::value)> @@ -27,27 +25,29 @@ constexpr bool has_value(int) { return t template <class> constexpr bool has_value(long) { return false; } template <class T> constexpr bool has_value() { return has_value<T>(0); } +struct Dummy {}; template <class T, std::size_t N> void test() { - static_assert(has_value<T>(), ""); static_assert((std::is_base_of<std::integral_constant<std::size_t, N>, std::tuple_size<T> >::value), ""); - static_assert(has_value<const T>(), ""); static_assert((std::is_base_of<std::integral_constant<std::size_t, N>, std::tuple_size<const T> >::value), ""); - static_assert(has_value<volatile T>(), ""); static_assert((std::is_base_of<std::integral_constant<std::size_t, N>, std::tuple_size<volatile T> >::value), ""); - - static_assert(has_value<const volatile T>(), ""); static_assert((std::is_base_of<std::integral_constant<std::size_t, N>, std::tuple_size<const volatile T> >::value), ""); - { - static_assert(!has_value<T &>(), ""); - static_assert(!has_value<T *>(), ""); - } +} + +void test_tuple_size_value_sfinae() { + // Test that the ::value member does not exist + static_assert(has_value<std::tuple<int> const>(), ""); + static_assert(has_value<std::pair<int, long> volatile>(), ""); + static_assert(!has_value<int>(), ""); + static_assert(!has_value<const int>(), ""); + static_assert(!has_value<volatile void>(), ""); + static_assert(!has_value<const volatile std::tuple<int>&>(), ""); } int main() @@ -56,13 +56,5 @@ int main() test<std::tuple<int>, 1>(); test<std::tuple<char, int>, 2>(); test<std::tuple<char, char*, int>, 3>(); - test<std::pair<int, void*>, 2>(); - test<std::array<int, 42>, 42>(); - { - static_assert(!has_value<void>(), ""); - static_assert(!has_value<void*>(), ""); - static_assert(!has_value<int>(), ""); - static_assert(!has_value<std::pair<int, int>*>(), ""); - static_assert(!has_value<std::array<int, 42>&>(), ""); - } + test_tuple_size_value_sfinae(); } Modified: libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_v.fail.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_v.fail.cpp?rev=290846&r1=290845&r2=290846&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_v.fail.cpp (original) +++ libcxx/trunk/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple_size_v.fail.cpp Mon Jan 2 17:54:13 2017 @@ -22,5 +22,5 @@ int main() (void)std::tuple_size_v<std::tuple<> &>; // expected-note {{requested here}} (void)std::tuple_size_v<int>; // expected-note {{requested here}} (void)std::tuple_size_v<std::tuple<>*>; // expected-note {{requested here}} - // expected-error@tuple:* 3 {{no member named 'value'}} + // expected-error@tuple:* 3 {{implicit instantiation of undefined template}} } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits