diff options
5 files changed, 87 insertions, 23 deletions
diff --git a/libstdc++-v3/include/bits/chrono.h b/libstdc++-v3/include/bits/chrono.h index 81b92d7..e949076 100644 --- a/libstdc++-v3/include/bits/chrono.h +++ b/libstdc++-v3/include/bits/chrono.h @@ -505,26 +505,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { return numeric_limits<_Rep>::lowest(); } }; - /// @cond undocumented - - template<typename _Tp> - struct __is_ratio - : std::false_type - { }; - - template<intmax_t _Num, intmax_t _Den> - struct __is_ratio<ratio<_Num, _Den>> - : std::true_type - { }; - - /// @endcond - template<typename _Rep, typename _Period> class duration { - static_assert(!__is_duration<_Rep>::value, "rep cannot be a duration"); + static_assert(!__is_duration<_Rep>::value, + "rep cannot be a std::chrono::duration"); static_assert(__is_ratio<_Period>::value, - "period must be a specialization of ratio"); + "period must be a specialization of std::ratio"); static_assert(_Period::num > 0, "period must be positive"); template<typename _Rep2> diff --git a/libstdc++-v3/include/std/ratio b/libstdc++-v3/include/std/ratio index 183f1ae..1d285bf 100644 --- a/libstdc++-v3/include/std/ratio +++ b/libstdc++-v3/include/std/ratio @@ -289,9 +289,43 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// @cond undocumented + template<typename _Tp> + struct __is_ratio + : std::false_type + { }; + + template<intmax_t _Num, intmax_t _Den> + struct __is_ratio<ratio<_Num, _Den>> + : std::true_type + { }; + +#if __cpp_variable_templates + template<typename _Tp> + constexpr bool __is_ratio_v = false; + template<intmax_t _Num, intmax_t _Den> + constexpr bool __is_ratio_v<ratio<_Num, _Den>> = true; +#endif + + template<typename _R1, typename _R2> + constexpr bool + __are_both_ratios() noexcept + { +#if __cpp_variable_templates && __cpp_if_constexpr + if constexpr (__is_ratio_v<_R1>) + if constexpr (__is_ratio_v<_R2>) + return true; + return false; +#else + return __and_<__is_ratio<_R1>, __is_ratio<_R2>>::value; +#endif + } + template<typename _R1, typename _R2> struct __ratio_multiply { + static_assert(std::__are_both_ratios<_R1, _R2>(), + "both template arguments must be a std::ratio"); + private: static const intmax_t __gcd1 = __static_gcd<_R1::num, _R2::den>::value; @@ -356,7 +390,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _R1, typename _R2> struct ratio_equal : integral_constant<bool, _R1::num == _R2::num && _R1::den == _R2::den> - { }; + { + static_assert(std::__are_both_ratios<_R1, _R2>(), + "both template arguments must be a std::ratio"); + }; /// ratio_not_equal template<typename _R1, typename _R2> @@ -402,7 +439,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _R1, typename _R2> struct ratio_less : __ratio_less_impl<_R1, _R2>::type - { }; + { + static_assert(std::__are_both_ratios<_R1, _R2>(), + "both template arguments must be a std::ratio"); + }; /// ratio_less_equal template<typename _R1, typename _R2> @@ -430,13 +470,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template <typename _R1, typename _R2> inline constexpr bool ratio_less_v = ratio_less<_R1, _R2>::value; template <typename _R1, typename _R2> - inline constexpr bool ratio_less_equal_v = - ratio_less_equal<_R1, _R2>::value; + inline constexpr bool ratio_less_equal_v + = ratio_less_equal<_R1, _R2>::value; template <typename _R1, typename _R2> inline constexpr bool ratio_greater_v = ratio_greater<_R1, _R2>::value; template <typename _R1, typename _R2> inline constexpr bool ratio_greater_equal_v - = ratio_greater_equal<_R1, _R2>::value; + = ratio_greater_equal<_R1, _R2>::value; #endif // C++17 /// @cond undocumented @@ -513,6 +553,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _R1, typename _R2> struct __ratio_add { + static_assert(std::__are_both_ratios<_R1, _R2>(), + "both template arguments must be a std::ratio"); + typedef typename __ratio_add_impl<_R1, _R2>::type type; static constexpr intmax_t num = type::num; static constexpr intmax_t den = type::den; diff --git a/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg1.cc b/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg1.cc index 49c9fe7..1a1188b 100644 --- a/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg1.cc +++ b/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg1.cc @@ -29,4 +29,4 @@ void test01() test_type d; // { dg-error "required from here" } } -// { dg-error "rep cannot be a duration" "" { target *-*-* } 0 } +// { dg-error "rep cannot be a std::chrono::duration" "" { target *-*-* } 0 } diff --git a/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg2.cc b/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg2.cc index 23c5d47..cbdb7af 100644 --- a/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg2.cc +++ b/libstdc++-v3/testsuite/20_util/duration/requirements/typedefs_neg2.cc @@ -30,7 +30,7 @@ void test01() test_type d; // { dg-error "required from here" } } -// { dg-error "must be a specialization of ratio" "" { target *-*-* } 0 } +// { dg-error "must be a specialization of std::ratio" "" { target *-*-* } 0 } // { dg-prune-output "'num' is not a member of 'int'" } // { dg-prune-output "'den' is not a member of 'int'" } // { dg-prune-output "'int' is not a class, struct, or union type" } diff --git a/libstdc++-v3/testsuite/20_util/ratio/requirements/type_constraints.cc b/libstdc++-v3/testsuite/20_util/ratio/requirements/type_constraints.cc new file mode 100644 index 0000000..ebf09bc --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/ratio/requirements/type_constraints.cc @@ -0,0 +1,34 @@ +// { dg-do compile { target c++11 } } + +// C++11 20.10.1 [ratio.general] +// if the template argument types R1 and R2 are not specializations of the +// ratio template, the program is ill-formed. + +#include <ratio> + +using namespace std; + +// A type that looks like std::ratio but isn't. +template<int> struct Ratty { static constexpr int num = 1, den = 1; }; + +using T1 = ratio_add<Ratty<1>, Ratty<1>>::type; // { dg-error "here" } +using T2 = ratio_subtract<Ratty<3>, Ratty<3>>::type; // { dg-error "here" } +using T3 = ratio_multiply<Ratty<3>, Ratty<3>>::type; // { dg-error "here" } +using T4 = ratio_divide<Ratty<4>, Ratty<4>>::type; // { dg-error "here" } +using T5 = ratio_equal<Ratty<5>, Ratty<5>>::type; // { dg-error "here" } +using T6 = ratio_not_equal<Ratty<6>, Ratty<6>>::type; // { dg-error "here" } +using T7 = ratio_less<Ratty<7>, Ratty<7>>::type; // { dg-error "here" } +using T8 = ratio_less_equal<Ratty<8>, Ratty<8>>::type; // { dg-error "here" } +using T9 = ratio_greater<Ratty<9>, Ratty<9>>::type; // { dg-error "here" } +using T10 = ratio_greater_equal<Ratty<10>, Ratty<10>>::type; // { dg-error "here" } + +#if __cplusplus >= 201703L +bool B11 = ratio_equal_v<Ratty<11>, Ratty<11>>; // { dg-error "here" "" { target c++17 } } +bool B12 = ratio_not_equal_v<Ratty<12>, Ratty<12>>; // { dg-error "here" "" { target c++17 } } +bool B13 = ratio_less_v<Ratty<13>, Ratty<13>>; // { dg-error "here" "" { target c++17 } } +bool B14 = ratio_less_equal_v<Ratty<14>, Ratty<14>>; // { dg-error "here" "" { target c++17 } } +bool B15 = ratio_greater_v<Ratty<15>, Ratty<15>>; // { dg-error "here" "" { target c++17 } } +bool B16 = ratio_greater_equal_v<Ratty<16>, Ratty<16>>; // { dg-error "here" "" { target c++17 } } +#endif + +// { dg-error "static assertion failed" "" { target *-*-* } 0 } |