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