sparrow ..
Loading...
Searching...
No Matches
nested_less.hpp
Go to the documentation of this file.
1// Copyright 2024 Man Group Operations Limited
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or mplied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15
16#pragma once
17
20
21namespace sparrow
22{
23 namespace detail
24 {
25 // nested eq / nested hash
26 template <class T>
28
29 // scalars
30 template <class T>
31 requires std::is_scalar_v<T>
32 struct nested_less<T>
33 {
34 [[nodiscard]] constexpr bool operator()(const T& a, const T& b) const noexcept
35 {
36 return a < b;
37 }
38 };
39
40 template <is_express_layout_desire T>
41 struct nested_less<T>
42 {
43 [[nodiscard]] constexpr bool operator()(const T& a, const T& b) const noexcept
44 {
45 return nested_less<typename T::value_type>{}(a.get(), b.get());
46 }
47 };
48
49 // nullables
50 template <class T>
51 requires is_nullable_like<T>
52 struct nested_less<T>
53 {
54 [[nodiscard]] constexpr bool operator()(const T& a, const T& b) const
55 {
56 // if one is null and the other is not then the null is less
57 // both are null:
58 if (!a.has_value() && !b.has_value())
59 {
60 return false;
61 }
62 // a is null, b is not
63 else if (!a.has_value())
64 {
65 return true;
66 }
67 // a is not null, b is
68 else if (!b.has_value())
69 {
70 return false;
71 }
72 else
73 {
74 // both are not null
75 return nested_less<typename T::value_type>{}(a.value(), b.value());
76 }
77 }
78 };
79
80 // tuple like
81 template <class T>
82 requires tuple_like<T>
83 struct nested_less<T>
84 {
85 [[nodiscard]] constexpr bool operator()(const T& a, const T& b) const
86 {
87 constexpr std::size_t N = std::tuple_size_v<T>;
88 bool is_less = false;
90 [&](auto i)
91 {
92 constexpr std::size_t index = decltype(i)::value;
93 using tuple_element_type = std::decay_t<std::tuple_element_t<decltype(i)::value, T>>;
94
95 const auto& a_val = std::get<index>(a);
96 const auto& b_val = std::get<index>(b);
97
98 // a < b
99 if (nested_less<tuple_element_type>{}(a_val, b_val))
100 {
101 is_less = true;
102 return false; // break
103 }
104 // a >= b
105 else if (nested_less<tuple_element_type>{}(b_val, a_val))
106 {
107 is_less = false;
108 return false; // break
109 }
110 // a == b
111 else
112 {
113 is_less = false;
114 return true; // continue
115 }
116 }
117 );
118 return is_less;
119 }
120 };
121
122 // ranges (and not tuple like)
123 template <class T>
124 requires(std::ranges::input_range<T> && !tuple_like<T>)
125 struct nested_less<T>
126 {
127 [[nodiscard]] constexpr bool operator()(const T& a, const T& b) const
128 {
129 using value_type = std::decay_t<std::ranges::range_value_t<T>>;
130 return std::ranges::lexicographical_compare(a, b, nested_less<value_type>{});
131 }
132 };
133
134 // variants
135 template <class T>
136 requires variant_like<T>
137 struct nested_less<T>
138 {
139 [[nodiscard]] constexpr bool operator()(const T& a, const T& b) const
140 {
141 if (a.index() != b.index())
142 {
143 return a.index() < b.index();
144 }
145 return std::visit(
146 [&](const auto& a_val)
147 {
148 using value_type = std::decay_t<decltype(a_val)>;
149 const auto& b_val = std::get<value_type>(b);
150 return nested_less<value_type>{}(a_val, b_val);
151 },
152 a
153 );
154 }
155 };
156
157 } // namespace detail
158} // namespace sparrow
bool exitable_for_each_index(F &&f)
constexpr bool operator()(const T &a, const T &b) const noexcept
constexpr bool operator()(const T &a, const T &b) const