Author: ericwf Date: Mon Sep 7 19:13:57 2015 New Revision: 246977 URL: http://llvm.org/viewvc/llvm-project?rev=246977&view=rev Log: 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 Modified: libcxx/trunk/include/type_traits libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp Modified: libcxx/trunk/include/type_traits URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/type_traits?rev=246977&r1=246976&r2=246977&view=diff ============================================================================== --- libcxx/trunk/include/type_traits (original) +++ libcxx/trunk/include/type_traits Mon Sep 7 19:13:57 2015 @@ -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,23 +1537,46 @@ struct _LIBCPP_TYPE_VIS_ONLY common_type 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 _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, _Up> +struct __common_type2<_Tp, _Up, + typename __void_t<decltype( + true ? _VSTD::declval<_Tp>() : _VSTD::declval<_Up>() + )>::type> { -private: - static _Tp&& __t(); - static _Up&& __u(); - static bool __f(); -public: - typedef typename decay<decltype(__f() ? __t() : __u())>::type 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 _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, _Up, _Vp...> +struct __common_type_impl<__common_types<_Tp, _Up, _Vp...>, + typename __void_t<typename common_type<_Tp, _Up>::type>::type> { - typedef typename common_type<typename common_type<_Tp, _Up>::type, _Vp...>::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...> + : __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; #endif Modified: libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp?rev=246977&r1=246976&r2=246977&view=diff ============================================================================== --- libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp (original) +++ libcxx/trunk/test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp Mon Sep 7 19:13:57 2015 @@ -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), ""); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits