• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*!
2 @file
3 Defines `boost::hana::less`.
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_LESS_HPP
11 #define BOOST_HANA_LESS_HPP
12 
13 #include <boost/hana/fwd/less.hpp>
14 
15 #include <boost/hana/and.hpp>
16 #include <boost/hana/bool.hpp>
17 #include <boost/hana/concept/constant.hpp>
18 #include <boost/hana/concept/orderable.hpp>
19 #include <boost/hana/concept/product.hpp>
20 #include <boost/hana/concept/sequence.hpp>
21 #include <boost/hana/config.hpp>
22 #include <boost/hana/core/common.hpp>
23 #include <boost/hana/core/to.hpp>
24 #include <boost/hana/core/dispatch.hpp>
25 #include <boost/hana/detail/concepts.hpp>
26 #include <boost/hana/detail/has_common_embedding.hpp>
27 #include <boost/hana/detail/nested_than.hpp> // required by fwd decl
28 #include <boost/hana/equal.hpp>
29 #include <boost/hana/first.hpp>
30 #include <boost/hana/if.hpp>
31 #include <boost/hana/less_equal.hpp>
32 #include <boost/hana/lexicographical_compare.hpp>
33 #include <boost/hana/or.hpp>
34 #include <boost/hana/second.hpp>
35 #include <boost/hana/value.hpp>
36 
37 
38 BOOST_HANA_NAMESPACE_BEGIN
39     //! @cond
40     template <typename X, typename Y>
operator ()(X && x,Y && y) const41     constexpr auto less_t::operator()(X&& x, Y&& y) const {
42         using T = typename hana::tag_of<X>::type;
43         using U = typename hana::tag_of<Y>::type;
44         using Less = BOOST_HANA_DISPATCH_IF(decltype(less_impl<T, U>{}),
45             hana::Orderable<T>::value &&
46             hana::Orderable<U>::value &&
47             !is_default<less_impl<T, U>>::value
48         );
49 
50     #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
51         static_assert(hana::Orderable<T>::value,
52         "hana::less(x, y) requires 'x' to be Orderable");
53 
54         static_assert(hana::Orderable<U>::value,
55         "hana::less(x, y) requires 'y' to be Orderable");
56 
57         static_assert(!is_default<less_impl<T, U>>::value,
58         "hana::less(x, y) requires 'x' and 'y' to be embeddable "
59         "in a common Orderable");
60     #endif
61 
62         return Less::apply(static_cast<X&&>(x), static_cast<Y&&>(y));
63     }
64     //! @endcond
65 
66     template <typename T, typename U, bool condition>
67     struct less_impl<T, U, when<condition>> : default_ {
68         template <typename ...Args>
69         static constexpr auto apply(Args&& ...) = delete;
70     };
71 
72     // Cross-type overload
73     template <typename T, typename U>
74     struct less_impl<T, U, when<
75         detail::has_nontrivial_common_embedding<Orderable, T, U>::value &&
76         !detail::LessThanComparable<T, U>::value
77     >> {
78         using C = typename hana::common<T, U>::type;
79         template <typename X, typename Y>
applyless_impl80         static constexpr decltype(auto) apply(X&& x, Y&& y) {
81             return hana::less(hana::to<C>(static_cast<X&&>(x)),
82                               hana::to<C>(static_cast<Y&&>(y)));
83         }
84     };
85 
86     //////////////////////////////////////////////////////////////////////////
87     // Model for LessThanComparable data types
88     //////////////////////////////////////////////////////////////////////////
89     template <typename T, typename U>
90     struct less_impl<T, U, when<detail::LessThanComparable<T, U>::value>> {
91         template <typename X, typename Y>
applyless_impl92         static constexpr decltype(auto) apply(X&& x, Y&& y)
93         { return static_cast<X&&>(x) < static_cast<Y&&>(y); }
94     };
95 
96     //////////////////////////////////////////////////////////////////////////
97     // Model for Constants wrapping an Orderable
98     //////////////////////////////////////////////////////////////////////////
99     template <typename C>
100     struct less_impl<C, C, when<
101         hana::Constant<C>::value &&
102         Orderable<typename C::value_type>::value
103     >> {
104         template <typename X, typename Y>
applyless_impl105         static constexpr auto apply(X const&, Y const&) {
106             constexpr auto is_less = hana::less(hana::value<X>(), hana::value<Y>());
107             constexpr bool truth_value = hana::if_(is_less, true, false);
108             return hana::bool_c<truth_value>;
109         }
110     };
111 
112     //////////////////////////////////////////////////////////////////////////
113     // Model for Products
114     //////////////////////////////////////////////////////////////////////////
115     template <typename T, typename U>
116     struct less_impl<T, U, when<hana::Product<T>::value && hana::Product<U>::value>> {
117         template <typename X, typename Y>
applyless_impl118         static constexpr decltype(auto) apply(X const& x, Y const& y) {
119             return hana::or_(
120                 hana::less(hana::first(x), hana::first(y)),
121                 hana::and_(
122                     hana::less_equal(hana::first(x), hana::first(y)),
123                     hana::less(hana::second(x), hana::second(y))
124                 )
125             );
126         }
127     };
128 
129     //////////////////////////////////////////////////////////////////////////
130     // Model for Sequences
131     //////////////////////////////////////////////////////////////////////////
132     template <typename T, typename U>
133     struct less_impl<T, U, when<
134         hana::Sequence<T>::value && hana::Sequence<U>::value
135     >> {
136         template <typename Xs, typename Ys>
applyless_impl137         static constexpr auto apply(Xs const& xs, Ys const& ys)
138         { return hana::lexicographical_compare(xs, ys); }
139     };
140 BOOST_HANA_NAMESPACE_END
141 
142 #endif // !BOOST_HANA_LESS_HPP
143