aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3/include
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2019-05-07 23:46:39 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2019-05-07 23:46:39 +0100
commitf61a12b3957d4ec67b2c0f4999c7054f1cf8f605 (patch)
tree7b2d6ee6404f98073dbeaced1b32b4e093f7e6f6 /libstdc++-v3/include
parentf7f36e3dc102d8ffb776f31abb48c33b1b830ebe (diff)
downloadgcc-f61a12b3957d4ec67b2c0f4999c7054f1cf8f605.zip
gcc-f61a12b3957d4ec67b2c0f4999c7054f1cf8f605.tar.gz
gcc-f61a12b3957d4ec67b2c0f4999c7054f1cf8f605.tar.bz2
PR libstdc++/89102 implement new common_type rules (P0435R1, P0548R1)
This change ensures that std::common_type<> is a complete type (LWG 2408), and that std::common_type<T>, std::common_type<cv T1, cv T2>, and std::common_type<T1, T2, R...> will use program-defined specializations for std::common_type<T1, T2> (LWG 2465). The implementation of common_type<T1, T2, R...> is changed to use void_t, and the specializations for duration and time_point are modified to also use void_t instead of depending on implementation details of common_type. PR libstdc++/89102 * doc/xml/manual/intro.xml: Document DR 2408 and 2465 changes. * include/std/chrono (__duration_common_type_wrapper): Replace with ... (__duration_common_type): New helper. (common_type<chrono::duration<R1, P2>, chrono::duration<R2, P2>>): Use __duration_common_type. (__timepoint_common_type_wrapper): Replace with ... (__timepoint_common_type): New helper. (common_type<chrono::time_point<C, D2>, chrono::time_point<C, D2>>): Use __time_point_common_type. * include/std/type_traits (common_type<>): Define, as per LWG 2408. (__common_type_impl): If either argument is transformed by decay, use the common_type of the decayed types. (__common_type_impl<_Tp, _Up, _Tp, _Up>): If the types are already decayed, use __do_common_type_impl to get the common_type. (common_type<_Tp>): Use common_type<_Tp, _Tp>. (__do_member_type_wrapper, __member_type_wrapper) (__expanded_common_type_wrapper): Remove. (__common_type_pack, __common_type_fold): New helpers. (common_type<_Tp, _Up, _Vp...>): Use new helpers instead of __member_type_wrapper and __expanded_common_type_wrapper. * 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 single argument cases and argument types that should decay. * testsuite/20_util/common_type/requirements/sfinae_friendly_2.cc: Adjust expected error. * testsuite/20_util/duration/literals/range_neg.cc: Use zero for dg-error lineno. * testsuite/20_util/duration/requirements/typedefs_neg1.cc: Likewise. * testsuite/20_util/duration/requirements/typedefs_neg2.cc: Likewise. * testsuite/20_util/duration/requirements/typedefs_neg3.cc: Likewise. From-SVN: r270987
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r--libstdc++-v3/include/std/chrono45
-rw-r--r--libstdc++-v3/include/std/type_traits102
2 files changed, 83 insertions, 64 deletions
diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono
index 1d6326c..b7c1d75 100644
--- a/libstdc++-v3/include/std/chrono
+++ b/libstdc++-v3/include/std/chrono
@@ -67,48 +67,51 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// 20.11.4.3 specialization of common_type (for duration, sfinae-friendly)
+ template<typename _CT, typename _Period1, typename _Period2, typename = void>
+ struct __duration_common_type
+ { };
+
template<typename _CT, typename _Period1, typename _Period2>
- struct __duration_common_type_wrapper
+ struct __duration_common_type<_CT, _Period1, _Period2,
+ __void_t<typename _CT::type>>
{
private:
- typedef __static_gcd<_Period1::num, _Period2::num> __gcd_num;
- typedef __static_gcd<_Period1::den, _Period2::den> __gcd_den;
- typedef typename _CT::type __cr;
- typedef ratio<__gcd_num::value,
- (_Period1::den / __gcd_den::value) * _Period2::den> __r;
+ using __gcd_num = __static_gcd<_Period1::num, _Period2::num>;
+ using __gcd_den = __static_gcd<_Period1::den, _Period2::den>;
+ using __cr = typename _CT::type;
+ using __r = ratio<__gcd_num::value,
+ (_Period1::den / __gcd_den::value) * _Period2::den>;
+
public:
- typedef __success_type<chrono::duration<__cr, __r>> type;
+ using type = chrono::duration<__cr, __r>;
};
template<typename _Period1, typename _Period2>
- struct __duration_common_type_wrapper<__failure_type, _Period1, _Period2>
+ struct __duration_common_type<__failure_type, _Period1, _Period2>
{ typedef __failure_type type; };
template<typename _Rep1, typename _Period1, typename _Rep2, typename _Period2>
struct common_type<chrono::duration<_Rep1, _Period1>,
- chrono::duration<_Rep2, _Period2>>
- : public __duration_common_type_wrapper<typename __member_type_wrapper<
- common_type<_Rep1, _Rep2>>::type, _Period1, _Period2>::type
+ chrono::duration<_Rep2, _Period2>>
+ : __duration_common_type<common_type<_Rep1, _Rep2>, _Period1, _Period2>
{ };
// 20.11.4.3 specialization of common_type (for time_point, sfinae-friendly)
+ template<typename _CT, typename _Clock, typename = void>
+ struct __timepoint_common_type
+ { };
+
template<typename _CT, typename _Clock>
- struct __timepoint_common_type_wrapper
+ struct __timepoint_common_type<_CT, _Clock, __void_t<typename _CT::type>>
{
- typedef __success_type<chrono::time_point<_Clock, typename _CT::type>>
- type;
+ using type = chrono::time_point<_Clock, typename _CT::type>;
};
- template<typename _Clock>
- struct __timepoint_common_type_wrapper<__failure_type, _Clock>
- { typedef __failure_type type; };
-
template<typename _Clock, typename _Duration1, typename _Duration2>
struct common_type<chrono::time_point<_Clock, _Duration1>,
- chrono::time_point<_Clock, _Duration2>>
- : public __timepoint_common_type_wrapper<typename __member_type_wrapper<
- common_type<_Duration1, _Duration2>>::type, _Clock>::type
+ chrono::time_point<_Clock, _Duration2>>
+ : __timepoint_common_type<common_type<_Duration1, _Duration2>, _Clock>
{ };
namespace chrono
diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits
index 1d14c75..ea733e7 100644
--- a/libstdc++-v3/include/std/type_traits
+++ b/libstdc++-v3/include/std/type_traits
@@ -2106,6 +2106,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct conditional<false, _Iftrue, _Iffalse>
{ typedef _Iffalse type; };
+ // __void_t (std::void_t for C++11)
+ template<typename...> using __void_t = void;
+
/// common_type
template<typename... _Tp>
struct common_type;
@@ -2115,65 +2118,81 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
struct __do_common_type_impl
{
template<typename _Tp, typename _Up>
- static __success_type<typename decay<decltype
- (true ? std::declval<_Tp>()
- : std::declval<_Up>())>::type> _S_test(int);
+ using __cond_t
+ = decltype(true ? std::declval<_Tp>() : std::declval<_Up>());
+
+ template<typename _Tp, typename _Up>
+ static __success_type<typename decay<__cond_t<_Tp, _Up>>::type>
+ _S_test(int);
template<typename, typename>
- static __failure_type _S_test(...);
+ static __failure_type
+ _S_test(...);
};
- template<typename _Tp, typename _Up>
- struct __common_type_impl
- : private __do_common_type_impl
- {
- typedef decltype(_S_test<_Tp, _Up>(0)) type;
- };
-
- struct __do_member_type_wrapper
- {
- template<typename _Tp>
- static __success_type<typename _Tp::type> _S_test(int);
+ // If sizeof...(T) is zero, there shall be no member type.
+ template<>
+ struct common_type<>
+ { };
- template<typename>
- static __failure_type _S_test(...);
- };
+ // If sizeof...(T) is one, the same type, if any, as common_type_t<T0, T0>.
+ template<typename _Tp0>
+ struct common_type<_Tp0>
+ : public common_type<_Tp0, _Tp0>
+ { };
- template<typename _Tp>
- struct __member_type_wrapper
- : private __do_member_type_wrapper
+ // If sizeof...(T) is two, ...
+ template<typename _Tp1, typename _Tp2,
+ typename _Dp1 = typename decay<_Tp1>::type,
+ typename _Dp2 = typename decay<_Tp2>::type>
+ struct __common_type_impl
{
- typedef decltype(_S_test<_Tp>(0)) type;
+ // If is_same_v<T1, D1> is false or is_same_v<T2, D2> is false,
+ // let C denote the same type, if any, as common_type_t<D1, D2>.
+ using type = common_type<_Dp1, _Dp2>;
};
- template<typename _CTp, typename... _Args>
- struct __expanded_common_type_wrapper
+ template<typename _Tp1, typename _Tp2>
+ struct __common_type_impl<_Tp1, _Tp2, _Tp1, _Tp2>
+ : private __do_common_type_impl
{
- typedef common_type<typename _CTp::type, _Args...> type;
+ // Otherwise, if decay_t<decltype(false ? declval<D1>() : declval<D2>())>
+ // denotes a valid type, let C denote that type.
+ using type = decltype(_S_test<_Tp1, _Tp2>(0));
};
- template<typename... _Args>
- struct __expanded_common_type_wrapper<__failure_type, _Args...>
- { typedef __failure_type type; };
+ // If sizeof...(T) is two, ...
+ template<typename _Tp1, typename _Tp2>
+ struct common_type<_Tp1, _Tp2>
+ : public __common_type_impl<_Tp1, _Tp2>::type
+ { };
- template<>
- struct common_type<>
+ template<typename...>
+ struct __common_type_pack
{ };
- template<typename _Tp>
- struct common_type<_Tp>
- : common_type<_Tp, _Tp>
+ template<typename, typename, typename = void>
+ struct __common_type_fold;
+
+ // If sizeof...(T) is greater than two, ...
+ template<typename _Tp1, typename _Tp2, typename... _Rp>
+ struct common_type<_Tp1, _Tp2, _Rp...>
+ : public __common_type_fold<common_type<_Tp1, _Tp2>,
+ __common_type_pack<_Rp...>>
{ };
- template<typename _Tp, typename _Up>
- struct common_type<_Tp, _Up>
- : public __common_type_impl<_Tp, _Up>::type
+ // Let C denote the same type, if any, as common_type_t<T1, T2>.
+ // If there is such a type C, type shall denote the same type, if any,
+ // as common_type_t<C, R...>.
+ template<typename _CTp, typename... _Rp>
+ struct __common_type_fold<_CTp, __common_type_pack<_Rp...>,
+ __void_t<typename _CTp::type>>
+ : public common_type<typename _CTp::type, _Rp...>
{ };
- template<typename _Tp, typename _Up, typename... _Vp>
- struct common_type<_Tp, _Up, _Vp...>
- : public __expanded_common_type_wrapper<typename __member_type_wrapper<
- common_type<_Tp, _Up>>::type, _Vp...>::type
+ // Otherwise, there shall be no member type.
+ template<typename _CTp, typename _Rp>
+ struct __common_type_fold<_CTp, _Rp, void>
{ };
template<typename _Tp, bool = is_enum<_Tp>::value>
@@ -2446,9 +2465,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<bool _Cond, typename _Tp = void>
using __enable_if_t = typename enable_if<_Cond, _Tp>::type;
- // __void_t (std::void_t for C++11)
- template<typename...> using __void_t = void;
-
#if __cplusplus >= 201703L || !defined(__STRICT_ANSI__) // c++17 or gnu++11
#define __cpp_lib_void_t 201411
/// A metafunction that always yields void, used for detecting valid types.