From 65a6f6422165f5a20e16335b670a67682a4f2ec0 Mon Sep 17 00:00:00 2001 From: Eric Fiselier Date: Tue, 8 Sep 2015 00:13:57 +0000 Subject: [PATCH] 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 git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@246977 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/type_traits | 61 +++++++++++++------ .../meta.trans.other/common_type.pass.cpp | 58 ++++++++++++++++-- 2 files changed, 95 insertions(+), 24 deletions(-) diff --git a/include/type_traits b/include/type_traits index 1aa4f6625..e496c382a 100644 --- a/include/type_traits +++ b/include/type_traits @@ -1517,21 +1517,19 @@ public: template 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::type type; + typedef typename decay() : _VSTD::declval<_Up>() + )>::type type; }; #else // _LIBCPP_HAS_NO_VARIADICS -template struct common_type; +// bullet 1 - sizeof...(Tp) == 0 + +template +struct _LIBCPP_TYPE_VIS_ONLY common_type {}; + +// bullet 2 - sizeof...(Tp) == 1 template 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 +struct __common_type2 {}; + +template +struct __common_type2<_Tp, _Up, + typename __void_t() : _VSTD::declval<_Up>() + )>::type> +{ + typedef typename decay() : _VSTD::declval<_Up>() + )>::type type; +}; + template struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, _Up> + : __common_type2<_Tp, _Up> {}; + +// bullet 4 - sizeof...(Tp) > 2 + +template struct __common_types; + +template +struct __common_type_impl {}; + +template +struct __common_type_impl<__common_types<_Tp, _Up, _Vp...>, + typename __void_t::type>::type> { -private: - static _Tp&& __t(); - static _Up&& __u(); - static bool __f(); -public: - typedef typename decay::type type; + typedef typename common_type< + typename common_type<_Tp, _Up>::type, _Vp... + >::type type; }; template struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, _Up, _Vp...> -{ - typedef typename common_type::type, _Vp...>::type type; -}; + : __common_type_impl<__common_types<_Tp, _Up, _Vp...> > {}; #if _LIBCPP_STD_VER > 11 template using common_type_t = typename common_type<_Tp...>::type; diff --git a/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp b/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp index 91bf7e765..e8611253c 100644 --- a/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp +++ b/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp @@ -13,11 +13,39 @@ #include +#include "test_macros.h" + +struct E {}; + +template +struct X { explicit X(T const&){} }; + +template +struct S { explicit S(T const&){} }; + +namespace std +{ + template + struct common_type > + { + typedef S type; + }; +} + +#if TEST_STD_VER >= 11 +template +struct no_common_type : std::true_type {}; + +template +struct no_common_type::type, void>::type> : std::false_type {}; +#endif // TEST_STD_VER >= 11 + int main() { static_assert((std::is_same::type, int>::value), ""); static_assert((std::is_same::type, char>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same, int>::value), ""); static_assert((std::is_same, char>::value), ""); #endif @@ -29,7 +57,7 @@ int main() static_assert((std::is_same::type, int>::value), ""); static_assert((std::is_same::type, int>::value), ""); - + static_assert((std::is_same::type, long>::value), ""); static_assert((std::is_same::type, long>::value), ""); static_assert((std::is_same::type, long>::value), ""); @@ -38,15 +66,37 @@ int main() static_assert((std::is_same::type, double>::value), ""); static_assert((std::is_same::type, int>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same, double>::value), ""); static_assert((std::is_same, int>::value), ""); #endif static_assert((std::is_same::type, double>::value), ""); static_assert((std::is_same::type, long long>::value), ""); -#if _LIBCPP_STD_VER > 11 +#if TEST_STD_VER > 11 static_assert((std::is_same, double>::value), ""); static_assert((std::is_same, long long>::value), ""); #endif + + static_assert((std::is_same::type, void>::value), ""); + static_assert((std::is_same::type, void>::value), ""); + static_assert((std::is_same::type, void>::value), ""); + static_assert((std::is_same::type, void>::value), ""); + + static_assert((std::is_same::type, void>::value), ""); + static_assert((std::is_same::type, void>::value), ""); + static_assert((std::is_same::type, void>::value), ""); + static_assert((std::is_same::type, void>::value), ""); + static_assert((std::is_same::type, void>::value), ""); + +#if TEST_STD_VER >= 11 + static_assert((no_common_type::value), ""); + static_assert((no_common_type::value), ""); + static_assert((no_common_type::value), ""); + static_assert((no_common_type >::value), ""); +#endif // TEST_STD_VER >= 11 + + static_assert((std::is_same >::type, S >::value), ""); + static_assert((std::is_same, S >::type, S >::value), ""); + static_assert((std::is_same >::type, S >::value), ""); }