This is a partial implementation of the revised std::common_type rules from P0435R1.
PR libstdc++/89102 (partial) * include/std/type_traits (common_type<>): Define. (common_type<T>): Derive from common_type<T, T>. * testsuite/20_util/common_type/requirements/explicit_instantiation.cc: Test zero-length template argument list. * testsuite/20_util/common_type/requirements/sfinae_friendly_1.cc: Test additional single argument cases. * testsuite/20_util/common_type/requirements/sfinae_friendly_2.cc: Adjust expected error. Tested powerpc64le-linux, committed to trunk. I think this could be backported to gcc-8-branch too. I have a complete patch for stage 1 which I'll post in a minute.
commit e5f7ac8d78351f41edd752c94c92fe1a389bdca7 Author: Jonathan Wakely <jwak...@redhat.com> Date: Wed Feb 6 16:27:03 2019 +0000 PR libstdc++/89102 fix common_type<> and common_type<T> specializations This is a partial implementation of the revised std::common_type rules from P0435R1. PR libstdc++/89102 (partial) * include/std/type_traits (common_type<>): Define. (common_type<T>): Derive from common_type<T, T>. * testsuite/20_util/common_type/requirements/explicit_instantiation.cc: Test zero-length template argument list. * testsuite/20_util/common_type/requirements/sfinae_friendly_1.cc: Test additional single argument cases. * testsuite/20_util/common_type/requirements/sfinae_friendly_2.cc: Adjust expected error. diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index f05a583cb04..bc2250d9dce 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -2132,9 +2132,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __expanded_common_type_wrapper<__failure_type, _Args...> { typedef __failure_type type; }; + template<> + struct common_type<> + { }; + template<typename _Tp> struct common_type<_Tp> - { typedef typename decay<_Tp>::type type; }; + : common_type<_Tp, _Tp> + { }; template<typename _Tp, typename _Up> struct common_type<_Tp, _Up> diff --git a/libstdc++-v3/testsuite/20_util/common_type/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/20_util/common_type/requirements/explicit_instantiation.cc index 28535a80d64..dc57ab5ad8e 100644 --- a/libstdc++-v3/testsuite/20_util/common_type/requirements/explicit_instantiation.cc +++ b/libstdc++-v3/testsuite/20_util/common_type/requirements/explicit_instantiation.cc @@ -30,6 +30,7 @@ namespace std typedef void test_type5; typedef const void test_type6; + template struct common_type<>; template struct common_type<test_type1>; template struct common_type<test_type1, test_type2>; template struct common_type<test_type1, test_type2, test_type3>; diff --git a/libstdc++-v3/testsuite/20_util/common_type/requirements/sfinae_friendly_1.cc b/libstdc++-v3/testsuite/20_util/common_type/requirements/sfinae_friendly_1.cc index 372c1a58378..9b94eb13434 100644 --- a/libstdc++-v3/testsuite/20_util/common_type/requirements/sfinae_friendly_1.cc +++ b/libstdc++-v3/testsuite/20_util/common_type/requirements/sfinae_friendly_1.cc @@ -159,7 +159,10 @@ namespace std { }; } +static_assert(is_type<std::common_type<int>, int>(), ""); +static_assert(is_type<std::common_type<const int>, int>(), ""); static_assert(is_type<std::common_type<int, int>, int>(), ""); +static_assert(is_type<std::common_type<const int, int>, int>(), ""); static_assert(is_type<std::common_type<ScEn, ScEn>, ScEn>(), ""); static_assert(is_type<std::common_type<UnscEn, UnscEn>, UnscEn>(), ""); static_assert(is_type<std::common_type<UnscEn, int>, int>(), ""); @@ -180,6 +183,8 @@ static_assert(is_type<std::common_type<int*, const volatile int*>, const volatile int*>(), ""); static_assert(is_type<std::common_type<void*, const volatile int*>, const volatile void*>(), ""); +static_assert(is_type<std::common_type<void>, void>(), ""); +static_assert(is_type<std::common_type<const void>, void>(), ""); static_assert(is_type<std::common_type<void, void>, void>(), ""); static_assert(is_type<std::common_type<const void, const void>, void>(), ""); static_assert(is_type<std::common_type<int&, int&&>, int>(), ""); @@ -316,6 +321,14 @@ static_assert(!has_type<std::common_type<UConv1, Abstract&&>>(), ""); static_assert(!has_type<std::common_type<std::initializer_list<int>, std::initializer_list<long>>>(), ""); +// PR libstdc++/89102 +static_assert(!has_type<std::common_type<int() &>>(), ""); +static_assert(!has_type<std::common_type<int() & noexcept>>(), ""); +static_assert(!has_type<std::common_type<int() const>>(), ""); +static_assert(!has_type<std::common_type<int(...) &>>(), ""); +static_assert(!has_type<std::common_type<int(...) & noexcept>>(), ""); +static_assert(!has_type<std::common_type<int(...) const>>(), ""); + void test(int i) { auto local_lmd1 = [=](int, double) { return i + i; }; diff --git a/libstdc++-v3/testsuite/20_util/common_type/requirements/sfinae_friendly_2.cc b/libstdc++-v3/testsuite/20_util/common_type/requirements/sfinae_friendly_2.cc index 64c8ea9339e..8f6f4ecd4d8 100644 --- a/libstdc++-v3/testsuite/20_util/common_type/requirements/sfinae_friendly_2.cc +++ b/libstdc++-v3/testsuite/20_util/common_type/requirements/sfinae_friendly_2.cc @@ -25,7 +25,7 @@ template<typename... Args> constexpr std::array<typename std::common_type<Args...>::type, sizeof...(Args)> -make_array(Args&&... args) // { dg-error "invalid use" } +make_array(Args&&... args) // { dg-error "no type.*common_type<>" } { typedef typename std::common_type<Args...>::type CT; return std::array<CT, sizeof...(Args)>{static_cast<CT>