1 /*! 2 @file 3 Adapts `std::ratio` for use with Hana. 4 5 @copyright Louis Dionne 2013-2017 6 Distributed under the Boost Software License, Version 1.0. 7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt) 8 */ 9 10 #ifndef BOOST_HANA_EXT_STD_RATIO_HPP 11 #define BOOST_HANA_EXT_STD_RATIO_HPP 12 13 #include <boost/hana/bool.hpp> 14 #include <boost/hana/concept/integral_constant.hpp> 15 #include <boost/hana/config.hpp> 16 #include <boost/hana/core/when.hpp> 17 #include <boost/hana/fwd/core/to.hpp> 18 #include <boost/hana/fwd/core/tag_of.hpp> 19 #include <boost/hana/fwd/div.hpp> 20 #include <boost/hana/fwd/equal.hpp> 21 #include <boost/hana/fwd/less.hpp> 22 #include <boost/hana/fwd/minus.hpp> 23 #include <boost/hana/fwd/mod.hpp> 24 #include <boost/hana/fwd/mult.hpp> 25 #include <boost/hana/fwd/one.hpp> 26 #include <boost/hana/fwd/plus.hpp> 27 #include <boost/hana/fwd/zero.hpp> 28 29 #include <cstdint> 30 #include <ratio> 31 #include <type_traits> 32 33 34 #ifdef BOOST_HANA_DOXYGEN_INVOKED 35 namespace std { 36 //! @ingroup group-ext-std 37 //! Adaptation of `std::ratio` for Hana. 38 //! 39 //! 40 //! Modeled concepts 41 //! ---------------- 42 //! 1. `Comparable`\n 43 //! `std::ratio`s are compared for equality using `std::ratio_equal`. 44 //! @include example/ext/std/ratio/comparable.cpp 45 //! 46 //! 2. `Orderable`\n 47 //! `std::ratio`s are ordered using `std::ratio_less`. 48 //! @include example/ext/std/ratio/orderable.cpp 49 //! 50 //! 3. `Monoid`, `Group`, `Ring`, and `EuclideanRing`\n 51 //! `std::ratio`s are added, subtracted, multiplied and divided using 52 //! `std::ratio_add`, `std::ratio_subtract`, `std::ratio_multiply` and 53 //! `std::ratio_divide`, respectively. Furthermore, the neutral element 54 //! for the additive operation is `std::ratio<0, 1>{}`, and the neutral 55 //! element for the multiplicative operation is `std::ratio<1, 1>{}`. 56 //! @include example/ext/std/ratio/arithmetic.cpp 57 template <std::intmax_t Num, std::intmax_t Denom> 58 class ratio { }; 59 } 60 #endif 61 62 63 BOOST_HANA_NAMESPACE_BEGIN 64 namespace ext { namespace std { struct ratio_tag; }} 65 66 template <std::intmax_t num, std::intmax_t den> 67 struct tag_of<std::ratio<num, den>> { 68 using type = ext::std::ratio_tag; 69 }; 70 71 ////////////////////////////////////////////////////////////////////////// 72 // Conversion from IntegralConstants 73 ////////////////////////////////////////////////////////////////////////// 74 template <typename C> 75 struct to_impl<ext::std::ratio_tag, C, when< 76 hana::IntegralConstant<C>::value 77 >> { 78 template <typename N> applyto_impl79 static constexpr auto apply(N const&) { 80 return std::ratio<N::value>{}; 81 } 82 }; 83 84 ////////////////////////////////////////////////////////////////////////// 85 // Comparable 86 ////////////////////////////////////////////////////////////////////////// 87 template <> 88 struct equal_impl<ext::std::ratio_tag, ext::std::ratio_tag> { 89 template <typename R1, typename R2> applyequal_impl90 static constexpr auto apply(R1 const&, R2 const&) 91 { return hana::bool_c<std::ratio_equal<R1, R2>::value>; } 92 }; 93 94 ////////////////////////////////////////////////////////////////////////// 95 // Orderable 96 ////////////////////////////////////////////////////////////////////////// 97 template <> 98 struct less_impl<ext::std::ratio_tag, ext::std::ratio_tag> { 99 template <typename R1, typename R2> applyless_impl100 static constexpr auto apply(R1 const&, R2 const&) 101 { return hana::bool_c<std::ratio_less<R1, R2>::value>; } 102 }; 103 104 ////////////////////////////////////////////////////////////////////////// 105 // Monoid 106 ////////////////////////////////////////////////////////////////////////// 107 template <> 108 struct plus_impl<ext::std::ratio_tag, ext::std::ratio_tag> { 109 template <typename R1, typename R2> applyplus_impl110 static constexpr std::ratio_add<R1, R2> apply(R1 const&, R2 const&) 111 { return {}; } 112 }; 113 114 template <> 115 struct zero_impl<ext::std::ratio_tag> { applyzero_impl116 static constexpr std::ratio<0> apply() 117 { return {}; } 118 }; 119 120 ////////////////////////////////////////////////////////////////////////// 121 // Group 122 ////////////////////////////////////////////////////////////////////////// 123 template <> 124 struct minus_impl<ext::std::ratio_tag, ext::std::ratio_tag> { 125 template <typename R1, typename R2> applyminus_impl126 static constexpr std::ratio_subtract<R1, R2> apply(R1 const&, R2 const&) 127 { return {}; } 128 }; 129 130 ////////////////////////////////////////////////////////////////////////// 131 // Ring 132 ////////////////////////////////////////////////////////////////////////// 133 template <> 134 struct mult_impl<ext::std::ratio_tag, ext::std::ratio_tag> { 135 template <typename R1, typename R2> applymult_impl136 static constexpr std::ratio_multiply<R1, R2> apply(R1 const&, R2 const&) 137 { return {}; } 138 }; 139 140 template <> 141 struct one_impl<ext::std::ratio_tag> { applyone_impl142 static constexpr std::ratio<1> apply() 143 { return {}; } 144 }; 145 146 ////////////////////////////////////////////////////////////////////////// 147 // EuclideanRing 148 ////////////////////////////////////////////////////////////////////////// 149 template <> 150 struct div_impl<ext::std::ratio_tag, ext::std::ratio_tag> { 151 template <typename R1, typename R2> applydiv_impl152 static constexpr std::ratio_divide<R1, R2> apply(R1 const&, R2 const&) 153 { return {}; } 154 }; 155 156 template <> 157 struct mod_impl<ext::std::ratio_tag, ext::std::ratio_tag> { 158 template <typename R1, typename R2> applymod_impl159 static constexpr std::ratio<0> apply(R1 const&, R2 const&) 160 { return {}; } 161 }; 162 BOOST_HANA_NAMESPACE_END 163 164 #endif // !BOOST_HANA_EXT_STD_RATIO_HPP 165