Imported Upstream version 1.64.0
[platform/upstream/boost.git] / boost / hana / lexicographical_compare.hpp
1 /*!
2 @file
3 Defines `boost::hana::lexicographical_compare`.
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_LEXICOGRAPHICAL_COMPARE_HPP
11 #define BOOST_HANA_LEXICOGRAPHICAL_COMPARE_HPP
12
13 #include <boost/hana/fwd/lexicographical_compare.hpp>
14
15 #include <boost/hana/bool.hpp>
16 #include <boost/hana/concept/iterable.hpp>
17 #include <boost/hana/config.hpp>
18 #include <boost/hana/core/dispatch.hpp>
19 #include <boost/hana/drop_front.hpp>
20 #include <boost/hana/front.hpp>
21 #include <boost/hana/if.hpp>
22 #include <boost/hana/is_empty.hpp>
23 #include <boost/hana/less.hpp>
24
25
26 BOOST_HANA_NAMESPACE_BEGIN
27     //! @cond
28     template <typename Xs, typename Ys>
29     constexpr auto lexicographical_compare_t::operator()(Xs const& xs, Ys const& ys) const {
30         return hana::lexicographical_compare(xs, ys, hana::less);
31     }
32
33     template <typename Xs, typename Ys, typename Pred>
34     constexpr auto lexicographical_compare_t::operator()(Xs const& xs, Ys const& ys, Pred const& pred) const {
35         using It1 = typename hana::tag_of<Xs>::type;
36         using It2 = typename hana::tag_of<Ys>::type;
37         using LexicographicalCompare = BOOST_HANA_DISPATCH_IF(
38             lexicographical_compare_impl<It1>,
39             hana::Iterable<It1>::value &&
40             hana::Iterable<It2>::value
41         );
42
43     #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
44         static_assert(hana::Iterable<It1>::value,
45         "hana::lexicographical_compare(xs, ys, pred) requires 'xs' to be Iterable");
46
47         static_assert(hana::Iterable<It2>::value,
48         "hana::lexicographical_compare(xs, ys, pred) requires 'ys' to be Iterable");
49     #endif
50
51         return LexicographicalCompare::apply(xs, ys, pred);
52     }
53     //! @endcond
54
55     template <typename It, bool condition>
56     struct lexicographical_compare_impl<It, when<condition>> : default_ {
57         template <typename Xs, typename Ys, typename Pred>
58         static constexpr auto
59         helper2(Xs const&, Ys const&, Pred const&, hana::true_)
60         { return hana::false_c; }
61
62         template <typename Xs, typename Ys, typename Pred>
63         static constexpr auto
64         helper2(Xs const& xs, Ys const& ys, Pred const& pred, hana::false_)
65         { return apply(hana::drop_front(xs), hana::drop_front(ys), pred); }
66
67         template <typename Xs, typename Ys, typename Pred>
68         static constexpr auto
69         helper2(Xs const& xs, Ys const& ys, Pred const& pred, bool is_greater)
70         { return is_greater ? false : apply(hana::drop_front(xs), hana::drop_front(ys), pred); }
71
72
73         template <typename Xs, typename Ys, typename Pred>
74         static constexpr auto
75         helper1(Xs const&, Ys const&, Pred const&, hana::true_)
76         { return hana::true_c; }
77
78         template <typename Xs, typename Ys, typename Pred>
79         static constexpr auto
80         helper1(Xs const& xs, Ys const& ys, Pred const& pred, hana::false_)
81         { return helper2(xs, ys, pred, hana::if_(pred(hana::front(ys), hana::front(xs)), hana::true_c, hana::false_c)); }
82
83         template <typename Xs, typename Ys, typename Pred>
84         static constexpr auto
85         helper1(Xs const& xs, Ys const& ys, Pred const& pred, bool is_less)
86         { return is_less ? true : helper2(xs, ys, pred, hana::if_(pred(hana::front(ys), hana::front(xs)), hana::true_c, hana::false_c)); }
87
88
89         template <typename Xs, typename Ys, typename Pred>
90         static constexpr auto
91         helper(Xs const&, Ys const& ys, Pred const&, hana::true_)
92         { return hana::not_(hana::is_empty(ys)); }
93
94         template <typename Xs, typename Ys, typename Pred>
95         static constexpr auto
96         helper(Xs const& xs, Ys const& ys, Pred const& pred, hana::false_)
97         { return helper1(xs, ys, pred, hana::if_(pred(hana::front(xs), hana::front(ys)), hana::true_c, hana::false_c)); }
98
99
100         template <typename Xs, typename Ys, typename Pred>
101         static constexpr auto apply(Xs const& xs, Ys const& ys, Pred const& pred) {
102             return helper(xs, ys, pred, hana::bool_c<
103                 decltype(hana::is_empty(xs))::value ||
104                 decltype(hana::is_empty(ys))::value
105             >);
106         }
107     };
108 BOOST_HANA_NAMESPACE_END
109
110 #endif // !BOOST_HANA_LEXICOGRAPHICAL_COMPARE_HPP