File indexing completed on 2025-01-30 09:43:38
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_HANA_MINUS_HPP
0011 #define BOOST_HANA_MINUS_HPP
0012
0013 #include <boost/hana/fwd/minus.hpp>
0014
0015 #include <boost/hana/concept/constant.hpp>
0016 #include <boost/hana/concept/group.hpp>
0017 #include <boost/hana/config.hpp>
0018 #include <boost/hana/core/common.hpp>
0019 #include <boost/hana/core/to.hpp>
0020 #include <boost/hana/core/dispatch.hpp>
0021 #include <boost/hana/detail/canonical_constant.hpp>
0022 #include <boost/hana/detail/has_common_embedding.hpp>
0023 #include <boost/hana/fwd/negate.hpp>
0024 #include <boost/hana/plus.hpp>
0025 #include <boost/hana/value.hpp>
0026
0027 #include <type_traits>
0028
0029
0030 namespace boost { namespace hana {
0031
0032 template <typename X, typename Y>
0033 constexpr decltype(auto) minus_t::operator()(X&& x, Y&& y) const {
0034 using T = typename hana::tag_of<X>::type;
0035 using U = typename hana::tag_of<Y>::type;
0036 using Minus = BOOST_HANA_DISPATCH_IF(decltype(minus_impl<T, U>{}),
0037 hana::Group<T>::value &&
0038 hana::Group<U>::value
0039 );
0040
0041 #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
0042 static_assert(hana::Group<T>::value,
0043 "hana::minus(x, y) requires 'x' to be in a Group");
0044
0045 static_assert(hana::Group<U>::value,
0046 "hana::minus(x, y) requires 'y' to be in a Group");
0047 #endif
0048
0049 return Minus::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
0050 }
0051
0052
0053 template <typename T, typename U, bool condition>
0054 struct minus_impl<T, U, when<condition>> : default_ {
0055 template <typename ...Args>
0056 static constexpr auto apply(Args&& ...) = delete;
0057 };
0058
0059 template <typename T, bool condition>
0060 struct minus_impl<T, T, when<condition>> : default_ {
0061 template <typename X, typename Y>
0062 static constexpr decltype(auto) apply(X&& x, Y&& y) {
0063 return hana::plus(static_cast<X&&>(x),
0064 hana::negate(static_cast<Y&&>(y)));
0065 }
0066 };
0067
0068
0069 template <typename T, typename U>
0070 struct minus_impl<T, U, when<
0071 detail::has_nontrivial_common_embedding<Group, T, U>::value
0072 >> {
0073 using C = typename common<T, U>::type;
0074 template <typename X, typename Y>
0075 static constexpr decltype(auto) apply(X&& x, Y&& y) {
0076 return hana::minus(hana::to<C>(static_cast<X&&>(x)),
0077 hana::to<C>(static_cast<Y&&>(y)));
0078 }
0079 };
0080
0081
0082
0083
0084 template <typename T>
0085 struct minus_impl<T, T, when<std::is_arithmetic<T>::value &&
0086 !std::is_same<bool, T>::value>> {
0087 template <typename X, typename Y>
0088 static constexpr decltype(auto) apply(X&& x, Y&& y)
0089 { return static_cast<X&&>(x) - static_cast<Y&&>(y); }
0090 };
0091
0092
0093
0094
0095 namespace detail {
0096 template <typename C, typename X, typename Y>
0097 struct constant_from_minus {
0098 static constexpr auto value = hana::minus(hana::value<X>(), hana::value<Y>());
0099 using hana_tag = detail::CanonicalConstant<typename C::value_type>;
0100 };
0101 }
0102
0103 template <typename C>
0104 struct minus_impl<C, C, when<
0105 hana::Constant<C>::value &&
0106 Group<typename C::value_type>::value
0107 >> {
0108 template <typename X, typename Y>
0109 static constexpr decltype(auto) apply(X const&, Y const&)
0110 { return hana::to<C>(detail::constant_from_minus<C, X, Y>{}); }
0111 };
0112 }}
0113
0114 #endif