sparrow 0.3.0
Loading...
Searching...
No Matches
nested_eq.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>
29 struct nested_eq;
30
31 // scalars
32 template <class T>
33 requires std::is_scalar_v<T>
34 struct nested_eq<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_eq<T>
44 {
45 [[nodiscard]] bool operator()(const T& a, const T& b) const
46 {
47 return nested_eq<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_eq<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 true;
63 }
64 // a or b is null
65 else if (!a.has_value() || !b.has_value())
66 {
67 return false;
68 }
69 else
70 {
71 // both are not null
72 return nested_eq<typename T::value_type>{}(a.value(), b.value());
73 }
74 }
75 };
76
77 // tuple like
78 template <class T>
79 requires tuple_like<T>
80 struct nested_eq<T>
81 {
82 [[nodiscard]] bool operator()(const T& a, const T& b) const
83 {
84 constexpr std::size_t N = std::tuple_size_v<T>;
86 [&](auto i)
87 {
88 constexpr std::size_t index = decltype(i)::value;
89 using tuple_element_type = std::decay_t<std::tuple_element_t<decltype(i)::value, T>>;
90
91 const auto& a_val = std::get<index>(a);
92 const auto& b_val = std::get<index>(b);
93
94 return nested_eq<tuple_element_type>{}(a_val, b_val);
95 }
96 );
97 }
98 };
99
100 // ranges (and not tuple like)
101 template <class T>
102 requires(std::ranges::input_range<T> && !tuple_like<T>)
103 struct nested_eq<T>
104 {
105 [[nodiscard]] bool operator()(const T& a, const T& b) const
106 {
107 return std::ranges::equal(a, b, nested_eq<std::ranges::range_value_t<T>>{});
108 }
109 };
110
111 // variants
112 template <class T>
113 requires variant_like<T>
114 struct nested_eq<T>
115 {
116 [[nodiscard]] bool operator()(const T& a, const T& b) const
117 {
118 if (a.index() != b.index())
119 {
120 return false;
121 }
122 return std::visit(
123 [&](const auto& a_val)
124 {
125 using value_type = std::decay_t<decltype(a_val)>;
126 const auto& b_val = std::get<value_type>(b);
127 return nested_eq<value_type>{}(a_val, b_val);
128 },
129 a
130 );
131 }
132 };
133 } // namespace detail
134} // namespace sparrow
bool exitable_for_each_index(F &&f)
bool operator()(const T &a, const T &b) const
Definition nested_eq.hpp:36