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