sparrow 0.3.0
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
18#include <vector>
19
22
23namespace sparrow
24{
25 namespace detail
26 {
27 // nested eq / nested hash
28 template <class T>
30
31 // scalars
32 template <class T>
33 requires std::is_scalar_v<T>
34 struct nested_less<T>
35 {
36 [[nodiscard]] bool operator()(const T& a, const T& b) const
37 {
38 return a < b;
39 }
40 };
41
42 template <is_express_layout_desire T>
43 struct nested_less<T>
44 {
45 [[nodiscard]] bool operator()(const T& a, const T& b) const
46 {
47 return nested_less<typename T::value_type>{}(a.get(), b.get());
48 }
49 };
50
51 // nullables
52 template <class T>
53 requires is_nullable_like<T>
54 struct nested_less<T>
55 {
56 [[nodiscard]] bool operator()(const T& a, const T& b) const
57 {
58 // if one is null and the other is not then the null is less
59 // both are null:
60 if (!a.has_value() && !b.has_value())
61 {
62 return false;
63 }
64 // a is null, b is not
65 else if (!a.has_value())
66 {
67 return true;
68 }
69 // a is not null, b is
70 else if (!b.has_value())
71 {
72 return false;
73 }
74 else
75 {
76 // both are not null
77 return nested_less<typename T::value_type>{}(a.value(), b.value());
78 }
79 }
80 };
81
82 // tuple like
83 template <class T>
84 requires tuple_like<T>
85 struct nested_less<T>
86 {
87 [[nodiscard]] bool operator()(const T& a, const T& b) const
88 {
89 constexpr std::size_t N = std::tuple_size_v<T>;
90 bool is_less = false;
92 [&](auto i)
93 {
94 constexpr std::size_t index = decltype(i)::value;
95 using tuple_element_type = std::decay_t<std::tuple_element_t<decltype(i)::value, T>>;
96
97 const auto& a_val = std::get<index>(a);
98 const auto& b_val = std::get<index>(b);
99
100 // a < b
101 if (nested_less<tuple_element_type>{}(a_val, b_val))
102 {
103 is_less = true;
104 return false; // break
105 }
106 // a >= b
107 else if (nested_less<tuple_element_type>{}(b_val, a_val))
108 {
109 is_less = false;
110 return false; // break
111 }
112 // a == b
113 else
114 {
115 is_less = false;
116 return true; // continue
117 }
118 }
119 );
120 return is_less;
121 }
122 };
123
124 // ranges (and not tuple like)
125 template <class T>
126 requires(std::ranges::input_range<T> && !tuple_like<T>)
127 struct nested_less<T>
128 {
129 [[nodiscard]] bool operator()(const T& a, const T& b) const
130 {
131 using value_type = std::decay_t<std::ranges::range_value_t<T>>;
132 return std::ranges::lexicographical_compare(a, b, nested_less<value_type>{});
133 }
134 };
135
136 // variants
137 template <class T>
138 requires variant_like<T>
139 struct nested_less<T>
140 {
141 [[nodiscard]] bool operator()(const T& a, const T& b) const
142 {
143 if (a.index() != b.index())
144 {
145 return a.index() < b.index();
146 }
147 return std::visit(
148 [&](const auto& a_val)
149 {
150 using value_type = std::decay_t<decltype(a_val)>;
151 const auto& b_val = std::get<value_type>(b);
152 return nested_less<value_type>{}(a_val, b_val);
153 },
154 a
155 );
156 }
157 };
158
159 } // namespace detail
160} // namespace sparrow
bool exitable_for_each_index(F &&f)
bool operator()(const T &a, const T &b) const