Index: include/type_traits =================================================================== --- include/type_traits +++ include/type_traits @@ -1450,21 +1450,17 @@ 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() : 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> @@ -1472,23 +1468,40 @@ typedef typename decay<_Tp>::type type; }; +// bullet 3 - sizeof...(Tp) == 2 + +template +struct __common_type2 {}; + template -struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, _Up> +struct __common_type2<_Tp, _Up, + typename __void_t() : declval<_Up>())>::type> { -private: - static _Tp&& __t(); - static _Up&& __u(); - static bool __f(); -public: - typedef typename decay::type type; + typedef typename decay() : 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 _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, _Up, _Vp...> +struct __common_type_impl<__common_types<_Tp, _Up, _Vp...>, + typename __void_t::type>::type> { typedef typename common_type::type, _Vp...>::type type; }; +template +struct _LIBCPP_TYPE_VIS_ONLY common_type<_Tp, _Up, _Vp...> + : __common_type_impl<__common_types<_Tp, _Up, _Vp...> > {}; + #if _LIBCPP_STD_VER > 11 template using common_type_t = typename common_type<_Tp...>::type; #endif Index: test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp =================================================================== --- test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp +++ test/std/utilities/meta/meta.trans/meta.trans.other/common_type.pass.cpp @@ -13,6 +13,32 @@ #include +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; + }; +} + +#ifndef _LIBCPP_HAS_NO_VARIADICS +template +struct no_common_type : std::true_type {}; + +template +struct no_common_type::type, void>::type> : std::false_type {}; +#endif // _LIBCPP_HAS_NO_VARIADICS + int main() { static_assert((std::is_same::type, int>::value), ""); @@ -29,7 +55,7 @@ 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), ""); @@ -49,4 +75,26 @@ 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), ""); + +#ifndef _LIBCPP_HAS_NO_VARIADICS + 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 // _LIBCPP_HAS_NO_VARIADICS + + 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), ""); }