forked from OSchip/llvm-project
make common_type SFINAE-friendly and support void. Patch from Agustin Berge.
This patch also fixes PR22135. (https://llvm.org/bugs/show_bug.cgi?id=22135) See the review for more information: http://reviews.llvm.org/D6964 llvm-svn: 246977
This commit is contained in:
parent
bb9a6ccfa8
commit
21dfbfb426
|
@ -1517,21 +1517,19 @@ public:
|
|||
template <class _Tp, class _Up>
|
||||
struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, _Up, void>
|
||||
{
|
||||
private:
|
||||
#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
static _Tp&& __t();
|
||||
static _Up&& __u();
|
||||
#else // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
static _Tp __t();
|
||||
static _Up __u();
|
||||
#endif // _LIBCPP_HAS_NO_RVALUE_REFERENCES
|
||||
public:
|
||||
typedef typename remove_reference<decltype(true ? __t() : __u())>::type type;
|
||||
typedef typename decay<decltype(
|
||||
true ? _VSTD::declval<_Tp>() : _VSTD::declval<_Up>()
|
||||
)>::type type;
|
||||
};
|
||||
|
||||
#else // _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
template <class ..._Tp> struct common_type;
|
||||
// bullet 1 - sizeof...(Tp) == 0
|
||||
|
||||
template <class ..._Tp>
|
||||
struct _LIBCPP_TYPE_VIS_ONLY common_type {};
|
||||
|
||||
// bullet 2 - sizeof...(Tp) == 1
|
||||
|
||||
template <class _Tp>
|
||||
struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp>
|
||||
|
@ -1539,22 +1537,45 @@ struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp>
|
|||
typedef typename decay<_Tp>::type type;
|
||||
};
|
||||
|
||||
// bullet 3 - sizeof...(Tp) == 2
|
||||
|
||||
template <class _Tp, class _Up, class = void>
|
||||
struct __common_type2 {};
|
||||
|
||||
template <class _Tp, class _Up>
|
||||
struct __common_type2<_Tp, _Up,
|
||||
typename __void_t<decltype(
|
||||
true ? _VSTD::declval<_Tp>() : _VSTD::declval<_Up>()
|
||||
)>::type>
|
||||
{
|
||||
typedef typename decay<decltype(
|
||||
true ? _VSTD::declval<_Tp>() : _VSTD::declval<_Up>()
|
||||
)>::type type;
|
||||
};
|
||||
|
||||
template <class _Tp, class _Up>
|
||||
struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, _Up>
|
||||
: __common_type2<_Tp, _Up> {};
|
||||
|
||||
// bullet 4 - sizeof...(Tp) > 2
|
||||
|
||||
template <class ...Tp> struct __common_types;
|
||||
|
||||
template <class, class = void>
|
||||
struct __common_type_impl {};
|
||||
|
||||
template <class _Tp, class _Up, class ..._Vp>
|
||||
struct __common_type_impl<__common_types<_Tp, _Up, _Vp...>,
|
||||
typename __void_t<typename common_type<_Tp, _Up>::type>::type>
|
||||
{
|
||||
private:
|
||||
static _Tp&& __t();
|
||||
static _Up&& __u();
|
||||
static bool __f();
|
||||
public:
|
||||
typedef typename decay<decltype(__f() ? __t() : __u())>::type type;
|
||||
typedef typename common_type<
|
||||
typename common_type<_Tp, _Up>::type, _Vp...
|
||||
>::type type;
|
||||
};
|
||||
|
||||
template <class _Tp, class _Up, class ..._Vp>
|
||||
struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, _Up, _Vp...>
|
||||
{
|
||||
typedef typename common_type<typename common_type<_Tp, _Up>::type, _Vp...>::type type;
|
||||
};
|
||||
: __common_type_impl<__common_types<_Tp, _Up, _Vp...> > {};
|
||||
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
template <class ..._Tp> using common_type_t = typename common_type<_Tp...>::type;
|
||||
|
|
|
@ -13,11 +13,39 @@
|
|||
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
struct E {};
|
||||
|
||||
template <class T>
|
||||
struct X { explicit X(T const&){} };
|
||||
|
||||
template <class T>
|
||||
struct S { explicit S(T const&){} };
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <typename T>
|
||||
struct common_type<T, ::S<T> >
|
||||
{
|
||||
typedef S<T> type;
|
||||
};
|
||||
}
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
template <class T, class U, class = void>
|
||||
struct no_common_type : std::true_type {};
|
||||
|
||||
template <class T, class U>
|
||||
struct no_common_type<T, U, typename std::conditional<false,
|
||||
typename std::common_type<T, U>::type, void>::type> : std::false_type {};
|
||||
#endif // TEST_STD_VER >= 11
|
||||
|
||||
int main()
|
||||
{
|
||||
static_assert((std::is_same<std::common_type<int>::type, int>::value), "");
|
||||
static_assert((std::is_same<std::common_type<char>::type, char>::value), "");
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
#if TEST_STD_VER > 11
|
||||
static_assert((std::is_same<std::common_type_t<int>, int>::value), "");
|
||||
static_assert((std::is_same<std::common_type_t<char>, char>::value), "");
|
||||
#endif
|
||||
|
@ -29,7 +57,7 @@ int main()
|
|||
|
||||
static_assert((std::is_same<std::common_type<int, int>::type, int>::value), "");
|
||||
static_assert((std::is_same<std::common_type<int, const int>::type, int>::value), "");
|
||||
|
||||
|
||||
static_assert((std::is_same<std::common_type<long, const int>::type, long>::value), "");
|
||||
static_assert((std::is_same<std::common_type<const long, int>::type, long>::value), "");
|
||||
static_assert((std::is_same<std::common_type<long, volatile int>::type, long>::value), "");
|
||||
|
@ -38,15 +66,37 @@ int main()
|
|||
|
||||
static_assert((std::is_same<std::common_type<double, char>::type, double>::value), "");
|
||||
static_assert((std::is_same<std::common_type<short, char>::type, int>::value), "");
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
#if TEST_STD_VER > 11
|
||||
static_assert((std::is_same<std::common_type_t<double, char>, double>::value), "");
|
||||
static_assert((std::is_same<std::common_type_t<short, char>, int>::value), "");
|
||||
#endif
|
||||
|
||||
static_assert((std::is_same<std::common_type<double, char, long long>::type, double>::value), "");
|
||||
static_assert((std::is_same<std::common_type<unsigned, char, long long>::type, long long>::value), "");
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
#if TEST_STD_VER > 11
|
||||
static_assert((std::is_same<std::common_type_t<double, char, long long>, double>::value), "");
|
||||
static_assert((std::is_same<std::common_type_t<unsigned, char, long long>, long long>::value), "");
|
||||
#endif
|
||||
|
||||
static_assert((std::is_same<std::common_type< void>::type, void>::value), "");
|
||||
static_assert((std::is_same<std::common_type<const void>::type, void>::value), "");
|
||||
static_assert((std::is_same<std::common_type< volatile void>::type, void>::value), "");
|
||||
static_assert((std::is_same<std::common_type<const volatile void>::type, void>::value), "");
|
||||
|
||||
static_assert((std::is_same<std::common_type<void, const void>::type, void>::value), "");
|
||||
static_assert((std::is_same<std::common_type<const void, void>::type, void>::value), "");
|
||||
static_assert((std::is_same<std::common_type<void, volatile void>::type, void>::value), "");
|
||||
static_assert((std::is_same<std::common_type<volatile void, void>::type, void>::value), "");
|
||||
static_assert((std::is_same<std::common_type<const void, const void>::type, void>::value), "");
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
static_assert((no_common_type<void, int>::value), "");
|
||||
static_assert((no_common_type<int, void>::value), "");
|
||||
static_assert((no_common_type<int, E>::value), "");
|
||||
static_assert((no_common_type<int, X<int> >::value), "");
|
||||
#endif // TEST_STD_VER >= 11
|
||||
|
||||
static_assert((std::is_same<std::common_type<int, S<int> >::type, S<int> >::value), "");
|
||||
static_assert((std::is_same<std::common_type<int, S<int>, S<int> >::type, S<int> >::value), "");
|
||||
static_assert((std::is_same<std::common_type<int, int, S<int> >::type, S<int> >::value), "");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue