165 lines
5.8 KiB
C++
165 lines
5.8 KiB
C++
/*!
|
|
@file
|
|
Adapts `std::ratio` for use with Hana.
|
|
|
|
@copyright Louis Dionne 2013-2016
|
|
Distributed under the Boost Software License, Version 1.0.
|
|
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
|
|
*/
|
|
|
|
#ifndef BOOST_HANA_EXT_STD_RATIO_HPP
|
|
#define BOOST_HANA_EXT_STD_RATIO_HPP
|
|
|
|
#include <boost/hana/bool.hpp>
|
|
#include <boost/hana/concept/integral_constant.hpp>
|
|
#include <boost/hana/config.hpp>
|
|
#include <boost/hana/core/when.hpp>
|
|
#include <boost/hana/fwd/core/to.hpp>
|
|
#include <boost/hana/fwd/core/tag_of.hpp>
|
|
#include <boost/hana/fwd/div.hpp>
|
|
#include <boost/hana/fwd/equal.hpp>
|
|
#include <boost/hana/fwd/less.hpp>
|
|
#include <boost/hana/fwd/minus.hpp>
|
|
#include <boost/hana/fwd/mod.hpp>
|
|
#include <boost/hana/fwd/mult.hpp>
|
|
#include <boost/hana/fwd/one.hpp>
|
|
#include <boost/hana/fwd/plus.hpp>
|
|
#include <boost/hana/fwd/zero.hpp>
|
|
|
|
#include <cstdint>
|
|
#include <ratio>
|
|
#include <type_traits>
|
|
|
|
|
|
#ifdef BOOST_HANA_DOXYGEN_INVOKED
|
|
namespace std {
|
|
//! @ingroup group-ext-std
|
|
//! Adaptation of `std::ratio` for Hana.
|
|
//!
|
|
//!
|
|
//! Modeled concepts
|
|
//! ----------------
|
|
//! 1. `Comparable`\n
|
|
//! `std::ratio`s are compared for equality using `std::ratio_equal`.
|
|
//! @include example/ext/std/ratio/comparable.cpp
|
|
//!
|
|
//! 2. `Orderable`\n
|
|
//! `std::ratio`s are ordered using `std::ratio_less`.
|
|
//! @include example/ext/std/ratio/orderable.cpp
|
|
//!
|
|
//! 3. `Monoid`, `Group`, `Ring`, and `EuclideanRing`\n
|
|
//! `std::ratio`s are added, subtracted, multiplied and divided using
|
|
//! `std::ratio_add`, `std::ratio_subtract`, `std::ratio_multiply` and
|
|
//! `std::ratio_divide`, respectively. Furthermore, the neutral element
|
|
//! for the additive operation is `std::ratio<0, 1>{}`, and the neutral
|
|
//! element for the multiplicative operation is `std::ratio<1, 1>{}`.
|
|
//! @include example/ext/std/ratio/arithmetic.cpp
|
|
template <std::intmax_t Num, std::intmax_t Denom>
|
|
class ratio { };
|
|
}
|
|
#endif
|
|
|
|
|
|
BOOST_HANA_NAMESPACE_BEGIN
|
|
namespace ext { namespace std { struct ratio_tag; }}
|
|
|
|
template <std::intmax_t num, std::intmax_t den>
|
|
struct tag_of<std::ratio<num, den>> {
|
|
using type = ext::std::ratio_tag;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Conversion from IntegralConstants
|
|
//////////////////////////////////////////////////////////////////////////
|
|
template <typename C>
|
|
struct to_impl<ext::std::ratio_tag, C, when<
|
|
hana::IntegralConstant<C>::value
|
|
>> {
|
|
template <typename N>
|
|
static constexpr auto apply(N const&) {
|
|
return std::ratio<N::value>{};
|
|
}
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Comparable
|
|
//////////////////////////////////////////////////////////////////////////
|
|
template <>
|
|
struct equal_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
|
|
template <typename R1, typename R2>
|
|
static constexpr auto apply(R1 const&, R2 const&)
|
|
{ return hana::bool_c<std::ratio_equal<R1, R2>::value>; }
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Orderable
|
|
//////////////////////////////////////////////////////////////////////////
|
|
template <>
|
|
struct less_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
|
|
template <typename R1, typename R2>
|
|
static constexpr auto apply(R1 const&, R2 const&)
|
|
{ return hana::bool_c<std::ratio_less<R1, R2>::value>; }
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Monoid
|
|
//////////////////////////////////////////////////////////////////////////
|
|
template <>
|
|
struct plus_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
|
|
template <typename R1, typename R2>
|
|
static constexpr std::ratio_add<R1, R2> apply(R1 const&, R2 const&)
|
|
{ return {}; }
|
|
};
|
|
|
|
template <>
|
|
struct zero_impl<ext::std::ratio_tag> {
|
|
static constexpr std::ratio<0> apply()
|
|
{ return {}; }
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Group
|
|
//////////////////////////////////////////////////////////////////////////
|
|
template <>
|
|
struct minus_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
|
|
template <typename R1, typename R2>
|
|
static constexpr std::ratio_subtract<R1, R2> apply(R1 const&, R2 const&)
|
|
{ return {}; }
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// Ring
|
|
//////////////////////////////////////////////////////////////////////////
|
|
template <>
|
|
struct mult_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
|
|
template <typename R1, typename R2>
|
|
static constexpr std::ratio_multiply<R1, R2> apply(R1 const&, R2 const&)
|
|
{ return {}; }
|
|
};
|
|
|
|
template <>
|
|
struct one_impl<ext::std::ratio_tag> {
|
|
static constexpr std::ratio<1> apply()
|
|
{ return {}; }
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// EuclideanRing
|
|
//////////////////////////////////////////////////////////////////////////
|
|
template <>
|
|
struct div_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
|
|
template <typename R1, typename R2>
|
|
static constexpr std::ratio_divide<R1, R2> apply(R1 const&, R2 const&)
|
|
{ return {}; }
|
|
};
|
|
|
|
template <>
|
|
struct mod_impl<ext::std::ratio_tag, ext::std::ratio_tag> {
|
|
template <typename R1, typename R2>
|
|
static constexpr std::ratio<0> apply(R1 const&, R2 const&)
|
|
{ return {}; }
|
|
};
|
|
BOOST_HANA_NAMESPACE_END
|
|
|
|
#endif // !BOOST_HANA_EXT_STD_RATIO_HPP
|