[libcxx] Re-implement LWG 2770 again: Fix tuple_size to work with structured bindings

Summary:
This patch attempts to re-implement a fix for LWG 2770, but not the actual specified PR. 

The PR for 2770 specifies tuple_size<T const> as only conditionally providing a `::value` member. However C++17 structured bindings require `tuple_size<T const>` to be complete only if  `tuple_size<T>` is also complete. Therefore this patch implements only provides the specialization `tuple_size<T CV>` iff `tuple_size<T>` is a complete type.

This fixes http://llvm.org/PR31513.

Reviewers: mclow.lists, rsmith, mpark

Subscribers: mpark, cfe-commits

Differential Revision: https://reviews.llvm.org/D28222

git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@291019 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Fiselier
2017-01-04 22:38:46 +00:00
parent e22af6b758
commit 06a0febbbd
7 changed files with 334 additions and 36 deletions

View File

@@ -24,30 +24,35 @@ _LIBCPP_BEGIN_NAMESPACE_STD
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;
};
#if !defined(_LIBCPP_CXX03_LANG)
template <class _Tp, class...>
using __enable_if_tuple_size_imp = _Tp;
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;
};
class _LIBCPP_TYPE_VIS_ONLY tuple_size<__enable_if_tuple_size_imp<
const _Tp,
typename enable_if<!is_volatile<_Tp>::value>::type,
integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
: public integral_constant<size_t, tuple_size<_Tp>::value> {};
template <class _Tp>
class _LIBCPP_TYPE_VIS_ONLY tuple_size<const _Tp>
: public __tuple_size_base_type<_Tp>::type {};
class _LIBCPP_TYPE_VIS_ONLY tuple_size<__enable_if_tuple_size_imp<
volatile _Tp,
typename enable_if<!is_const<_Tp>::value>::type,
integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
: public integral_constant<size_t, tuple_size<_Tp>::value> {};
template <class _Tp>
class _LIBCPP_TYPE_VIS_ONLY tuple_size<volatile _Tp>
: public __tuple_size_base_type<_Tp>::type {};
class _LIBCPP_TYPE_VIS_ONLY tuple_size<__enable_if_tuple_size_imp<
const volatile _Tp,
integral_constant<size_t, sizeof(tuple_size<_Tp>)>>>
: public integral_constant<size_t, tuple_size<_Tp>::value> {};
template <class _Tp>
class _LIBCPP_TYPE_VIS_ONLY tuple_size<const volatile _Tp>
: public __tuple_size_base_type<_Tp>::type {};
#else
template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_size<const _Tp> : tuple_size<_Tp> {};
template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_size<volatile _Tp> : tuple_size<_Tp> {};
template <class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_size<const volatile _Tp> : tuple_size<_Tp> {};
#endif
template <size_t _Ip, class _Tp> class _LIBCPP_TYPE_VIS_ONLY tuple_element;