• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 Hans Dembinski
2 //
3 // Distributed under the Boost Software License, Version 1.0.
4 // (See accompanying file LICENSE_1_0.txt
5 // or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7 #ifndef BOOST_HISTOGRAM_DETAIL_OPERATORS_HPP
8 #define BOOST_HISTOGRAM_DETAIL_OPERATORS_HPP
9 
10 #include <boost/histogram/detail/detect.hpp>
11 #include <boost/mp11/algorithm.hpp>
12 #include <boost/mp11/list.hpp>
13 #include <boost/mp11/utility.hpp>
14 
15 namespace boost {
16 namespace histogram {
17 namespace detail {
18 
19 template <class T, class U>
20 using if_not_same_and_has_eq =
21     std::enable_if_t<(!std::is_same<T, U>::value && has_method_eq<T, U>::value), bool>;
22 
23 // totally_ordered is for types with a <= b == !(a > b) [floats with NaN violate this]
24 // Derived must implement <,== for symmetric form and <,>,== for non-symmetric.
25 
26 // partially_ordered is for types with a <= b == a < b || a == b [for floats with NaN]
27 // Derived must implement <,== for the symmetric form and <,>,== for non-symmetric.
28 
29 template <class T, class U>
30 struct mirrored {
operator <(const U & a,const T & b)31   friend bool operator<(const U& a, const T& b) noexcept { return b > a; }
operator >(const U & a,const T & b)32   friend bool operator>(const U& a, const T& b) noexcept { return b < a; }
operator ==(const U & a,const T & b)33   friend bool operator==(const U& a, const T& b) noexcept { return b == a; }
operator <=(const U & a,const T & b)34   friend bool operator<=(const U& a, const T& b) noexcept { return b >= a; }
operator >=(const U & a,const T & b)35   friend bool operator>=(const U& a, const T& b) noexcept { return b <= a; }
operator !=(const U & a,const T & b)36   friend bool operator!=(const U& a, const T& b) noexcept { return b != a; }
37 };
38 
39 template <class T>
40 struct mirrored<T, void> {
41   template <class U>
operator <(const U & a,const T & b)42   friend if_not_same_and_has_eq<T, U> operator<(const U& a, const T& b) noexcept {
43     return b > a;
44   }
45   template <class U>
operator >(const U & a,const T & b)46   friend if_not_same_and_has_eq<T, U> operator>(const U& a, const T& b) noexcept {
47     return b < a;
48   }
49   template <class U>
operator ==(const U & a,const T & b)50   friend if_not_same_and_has_eq<T, U> operator==(const U& a, const T& b) noexcept {
51     return b == a;
52   }
53   template <class U>
operator <=(const U & a,const T & b)54   friend if_not_same_and_has_eq<T, U> operator<=(const U& a, const T& b) noexcept {
55     return b >= a;
56   }
57   template <class U>
operator >=(const U & a,const T & b)58   friend if_not_same_and_has_eq<T, U> operator>=(const U& a, const T& b) noexcept {
59     return b <= a;
60   }
61   template <class U>
operator !=(const U & a,const T & b)62   friend if_not_same_and_has_eq<T, U> operator!=(const U& a, const T& b) noexcept {
63     return b != a;
64   }
65 };
66 
67 template <class T>
68 struct mirrored<T, T> {
operator >(const T & a,const T & b)69   friend bool operator>(const T& a, const T& b) noexcept { return b.operator<(a); }
70 };
71 
72 template <class T, class U>
73 struct equality {
operator !=(const T & a,const U & b)74   friend bool operator!=(const T& a, const U& b) noexcept { return !a.operator==(b); }
75 };
76 
77 template <class T>
78 struct equality<T, void> {
79   template <class U>
operator !=(const T & a,const U & b)80   friend if_not_same_and_has_eq<T, U> operator!=(const T& a, const U& b) noexcept {
81     return !(a == b);
82   }
83 };
84 
85 template <class T, class U>
86 struct totally_ordered_impl : equality<T, U>, mirrored<T, U> {
operator <=(const T & a,const U & b)87   friend bool operator<=(const T& a, const U& b) noexcept { return !(a > b); }
operator >=(const T & a,const U & b)88   friend bool operator>=(const T& a, const U& b) noexcept { return !(a < b); }
89 };
90 
91 template <class T>
92 struct totally_ordered_impl<T, void> : equality<T, void>, mirrored<T, void> {
93   template <class U>
operator <=(const T & a,const U & b)94   friend if_not_same_and_has_eq<T, U> operator<=(const T& a, const U& b) noexcept {
95     return !(a > b);
96   }
97   template <class U>
operator >=(const T & a,const U & b)98   friend if_not_same_and_has_eq<T, U> operator>=(const T& a, const U& b) noexcept {
99     return !(a < b);
100   }
101 };
102 
103 template <class T, class... Ts>
104 using totally_ordered = mp11::mp_rename<
105     mp11::mp_product<totally_ordered_impl, mp11::mp_list<T>, mp11::mp_list<Ts...> >,
106     mp11::mp_inherit>;
107 
108 template <class T, class U>
109 struct partially_ordered_impl : equality<T, U>, mirrored<T, U> {
operator <=(const T & a,const U & b)110   friend bool operator<=(const T& a, const U& b) noexcept { return a < b || a == b; }
operator >=(const T & a,const U & b)111   friend bool operator>=(const T& a, const U& b) noexcept { return a > b || a == b; }
112 };
113 
114 template <class T>
115 struct partially_ordered_impl<T, void> : equality<T, void>, mirrored<T, void> {
116   template <class U>
operator <=(const T & a,const U & b)117   friend if_not_same_and_has_eq<T, U> operator<=(const T& a, const U& b) noexcept {
118     return a < b || a == b;
119   }
120   template <class U>
operator >=(const T & a,const U & b)121   friend if_not_same_and_has_eq<T, U> operator>=(const T& a, const U& b) noexcept {
122     return a > b || a == b;
123   }
124 };
125 
126 template <class T, class... Ts>
127 using partially_ordered = mp11::mp_rename<
128     mp11::mp_product<partially_ordered_impl, mp11::mp_list<T>, mp11::mp_list<Ts...> >,
129     mp11::mp_inherit>;
130 
131 } // namespace detail
132 } // namespace histogram
133 } // namespace boost
134 
135 #endif // BOOST_HISTOGRAM_DETAIL_OPERATORS_HPP
136