Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Compare.inl
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#include "Stroika/Foundation/Common/Concepts.h"
6
8
9 /*
10 ********************************************************************************
11 ********** ComparisonRelationDeclaration<TYPE, ACTUAL_COMPARER> ****************
12 ********************************************************************************
13 */
14 template <ComparisonRelationType KIND, typename ACTUAL_COMPARER>
15 requires (not is_reference_v<ACTUAL_COMPARER>)
16 template <typename... ARGS>
17 inline constexpr ComparisonRelationDeclaration<KIND, ACTUAL_COMPARER>::ComparisonRelationDeclaration (ARGS... args)
18#if !qCompilerAndStdLib_template_Requires_constraint_not_treated_constexpr_Buggy
19 requires (constructible_from<ACTUAL_COMPARER, ARGS...>)
20#endif
21 : ACTUAL_COMPARER{std::forward<ARGS> (args)...}
22 {
23 }
24
25 /*
26 ********************************************************************************
27 **************************** DeclareEqualsComparer *****************************
28 ********************************************************************************
29 */
30 template <typename FUNCTOR>
36
37 /*
38 ********************************************************************************
39 ******************************* DeclareInOrderComparer *************************
40 ********************************************************************************
41 */
42 template <typename FUNCTOR>
49
50 /*
51 ********************************************************************************
52 ********************* EqualsComparerAdapter<BASE_COMPARER> *********************
53 ********************************************************************************
54 */
55 template <typename ARG_T, IComparer<ARG_T> BASE_COMPARER>
56 constexpr EqualsComparerAdapter<ARG_T, BASE_COMPARER>::EqualsComparerAdapter (const BASE_COMPARER& baseComparer)
57 : fBASE_COMPARER_{baseComparer}
58 {
59 }
60 template <typename ARG_T, IComparer<ARG_T> BASE_COMPARER>
61 constexpr EqualsComparerAdapter<ARG_T, BASE_COMPARER>::EqualsComparerAdapter (BASE_COMPARER&& baseComparer)
62 : fBASE_COMPARER_{move (baseComparer)}
63 {
64 }
65 template <typename ARG_T, IComparer<ARG_T> BASE_COMPARER>
66 template <typename LT, typename RT>
67 constexpr bool EqualsComparerAdapter<ARG_T, BASE_COMPARER>::operator() (LT&& lhs, RT&& rhs) const
68 {
69 /*
70 * It would be nice to be able to use switch statement but use constexpr if because
71 * inappropriate 'cases' that wouldn't get executed might not compile -- LGP 2020-05-05
72 */
73 constexpr auto kRelationKind = ExtractComparisonTraits_v<ARG_T, BASE_COMPARER>;
74 auto baseComparison = fBASE_COMPARER_ (forward<LT> (lhs), forward<RT> (rhs));
75 if constexpr (kRelationKind == ComparisonRelationType::eEquals) {
76 return baseComparison;
77 }
78 if constexpr (kRelationKind == ComparisonRelationType::eStrictInOrder) {
79 if (baseComparison) {
80 return false; // if less, cannot be equal
81 }
82 else {
83 return not fBASE_COMPARER_ (forward<RT> (rhs), forward<LT> (lhs)); // if not (LHS < RHS), maybe RHS < LHS?
84 }
85 }
86 if constexpr (kRelationKind == ComparisonRelationType::eInOrderOrEquals) {
87 if (baseComparison) {
88 return fBASE_COMPARER_ (forward<RT> (rhs), forward<LT> (lhs)); // if (LHS <= RHS), then EQ if reverse true
89 }
90 else {
91 return false; // not not <=, then clearly not equal
92 }
93 }
94 if constexpr (kRelationKind == ComparisonRelationType::eThreeWayCompare) {
95 return baseComparison == strong_ordering::equal;
96 }
98 return false;
99 }
100
101 /*
102 ********************************************************************************
103 ********************* InOrderComparerAdapter<BASE_COMPARER> ********************
104 ********************************************************************************
105 */
106 template <typename ARG_T, IComparer<ARG_T> BASE_COMPARER>
107 requires (ExtractComparisonTraits_v<ARG_T, BASE_COMPARER> == ComparisonRelationType::eStrictInOrder or
108 ExtractComparisonTraits_v<ARG_T, BASE_COMPARER> == ComparisonRelationType::eInOrderOrEquals or
109 ExtractComparisonTraits_v<ARG_T, BASE_COMPARER> == ComparisonRelationType::eThreeWayCompare)
110 constexpr inline InOrderComparerAdapter<ARG_T, BASE_COMPARER>::InOrderComparerAdapter (const BASE_COMPARER& baseComparer)
111 : fBASE_COMPARER_{baseComparer}
112 {
113 }
114 template <typename ARG_T, IComparer<ARG_T> BASE_COMPARER>
115 requires (ExtractComparisonTraits_v<ARG_T, BASE_COMPARER> == ComparisonRelationType::eStrictInOrder or
116 ExtractComparisonTraits_v<ARG_T, BASE_COMPARER> == ComparisonRelationType::eInOrderOrEquals or
117 ExtractComparisonTraits_v<ARG_T, BASE_COMPARER> == ComparisonRelationType::eThreeWayCompare)
118 constexpr inline InOrderComparerAdapter<ARG_T, BASE_COMPARER>::InOrderComparerAdapter (BASE_COMPARER&& baseComparer)
119 : fBASE_COMPARER_{move (baseComparer)}
120 {
121 }
122 template <typename ARG_T, IComparer<ARG_T> BASE_COMPARER>
123 requires (ExtractComparisonTraits_v<ARG_T, BASE_COMPARER> == ComparisonRelationType::eStrictInOrder or
124 ExtractComparisonTraits_v<ARG_T, BASE_COMPARER> == ComparisonRelationType::eInOrderOrEquals or
125 ExtractComparisonTraits_v<ARG_T, BASE_COMPARER> == ComparisonRelationType::eThreeWayCompare)
126 template <typename LT, typename RT>
127 constexpr inline bool InOrderComparerAdapter<ARG_T, BASE_COMPARER>::operator() (LT&& lhs, RT&& rhs) const
128 {
129 /*
130 * It would be nice to be able to use switch statement but use constexpr if because
131 * inappropriate 'cases' that wouldn't get executed might not compile -- LGP 2020-05-05
132 */
133 constexpr auto kRelationKind = ExtractComparisonTraits_v<ARG_T, BASE_COMPARER>;
134 auto baseComparison = fBASE_COMPARER_ (forward<LT> (lhs), forward<RT> (rhs));
135 if constexpr (kRelationKind == ComparisonRelationType::eStrictInOrder) {
136 return baseComparison;
137 }
138 if constexpr (kRelationKind == ComparisonRelationType::eInOrderOrEquals) {
139 return baseComparison and not fBASE_COMPARER_ (forward<RT> (rhs), forward<LT> (lhs)); // eliminate equals case
140 }
141 if constexpr (kRelationKind == ComparisonRelationType::eThreeWayCompare) {
142 return baseComparison == strong_ordering::less;
143 }
145 return false;
146 }
147
148 /*
149 ********************************************************************************
150 ********************* ThreeWayComparerAdapter<BASE_COMPARER> *******************
151 ********************************************************************************
152 */
153 template <typename ARG_T, ITotallyOrderingComparer<ARG_T> BASE_COMPARER>
154 constexpr ThreeWayComparerAdapter<ARG_T, BASE_COMPARER>::ThreeWayComparerAdapter (const BASE_COMPARER& baseComparer)
155 : fBASE_COMPARER_{baseComparer}
156 {
157 }
158 template <typename ARG_T, ITotallyOrderingComparer<ARG_T> BASE_COMPARER>
159 constexpr ThreeWayComparerAdapter<ARG_T, BASE_COMPARER>::ThreeWayComparerAdapter (BASE_COMPARER&& baseComparer)
160 : fBASE_COMPARER_{move (baseComparer)}
161 {
162 }
163 template <typename ARG_T, ITotallyOrderingComparer<ARG_T> BASE_COMPARER>
164 template <typename LT, typename RT>
165 constexpr strong_ordering ThreeWayComparerAdapter<ARG_T, BASE_COMPARER>::operator() (LT&& lhs, RT&& rhs) const
166 {
167 /*
168 * It would be nice to be able to use switch statement but use constexpr if because
169 * inappropriate 'cases' that wouldn't get executed might not compile -- LGP 2020-05-05
170 */
171 constexpr auto kRelationKind = ExtractComparisonTraits_v<ARG_T, BASE_COMPARER>;
172 auto baseComparison = fBASE_COMPARER_ (forward<LT> (lhs), forward<RT> (rhs));
173 if constexpr (kRelationKind == ComparisonRelationType::eThreeWayCompare) {
174 return baseComparison;
175 }
176 if constexpr (kRelationKind == ComparisonRelationType::eStrictInOrder) {
177 if (baseComparison) {
178 return strong_ordering::less;
179 }
180 // if not <, then either equal or greater: if RHS < LHS, then LHS > RHS
181 return fBASE_COMPARER_ (forward<RT> (rhs), forward<LT> (lhs)) ? strong_ordering::greater : strong_ordering::equal;
182 }
184 return strong_ordering::equal;
185 }
186
187 /*
188 ********************************************************************************
189 *************** OptionalThreeWayCompare<T, TCOMPARER> **************************
190 ********************************************************************************
191 */
192 template <typename ARG_T, IComparer<ARG_T> TCOMPARER>
193 constexpr OptionalThreeWayComparer<ARG_T, TCOMPARER>::OptionalThreeWayComparer (TCOMPARER&& comparer)
194 : fTComparer_{move (comparer)}
195 {
196 }
197 template <typename ARG_T, IComparer<ARG_T> TCOMPARER>
198 constexpr OptionalThreeWayComparer<ARG_T, TCOMPARER>::OptionalThreeWayComparer (const TCOMPARER& comparer)
199 : fTComparer_{comparer}
200 {
201 }
202 template <typename ARG_T, IComparer<ARG_T> TCOMPARER>
203 constexpr strong_ordering OptionalThreeWayComparer<ARG_T, TCOMPARER>::operator() (const optional<ARG_T>& lhs, const optional<ARG_T>& rhs) const
204 {
205 if (lhs and rhs) {
206 return fTComparer_ (*lhs, *rhs);
207 }
208 if (not lhs and not rhs) {
209 return strong_ordering::equal;
210 }
211 // treat missing as less than present
212 if (lhs) {
213 return strong_ordering::greater;
214 }
215 else {
216 return strong_ordering::less;
217 }
218 }
219
220 /*
221 ********************************************************************************
222 *************************** CompareResultNormalizer ****************************
223 ********************************************************************************
224 */
225 template <typename FROM_INT_TYPE>
226 constexpr strong_ordering CompareResultNormalizer (FROM_INT_TYPE f)
227 {
228 if (f == 0) {
229 return strong_ordering::equal;
230 }
231 else {
232 Assert (f < 0 or f > 0);
233 return f < 0 ? strong_ordering::less : strong_ordering::greater;
234 }
235 }
236
237 /*
238 ********************************************************************************
239 ******************************* ReverseCompareOrder ****************************
240 ********************************************************************************
241 */
242 constexpr strong_ordering ReverseCompareOrder (strong_ordering so)
243 {
244 if (so == strong_ordering::less) {
245 return strong_ordering::greater;
246 }
247 else if (so == strong_ordering::greater) {
248 return strong_ordering::less;
249 }
250 return so;
251 }
252
253 /********************************DEPRECATED STUFF ************************************************** */
254 /********************************DEPRECATED STUFF ************************************************** */
255 /********************************DEPRECATED STUFF ************************************************** */
256
257 // @TODO SEEMS STILL NEEDED ON CLANG++-10???
258 // @TODO PROBABLY DEPRECATE THIS CLASS - and use compare_three_way directly
259#if __cpp_lib_three_way_comparison < 201907L
260 struct [[deprecated ("Since Stroika 3.0d1 - use std::compare_three_way")]] ThreeWayComparer {
261 template <typename LT, typename RT>
262 constexpr auto operator() (LT&& lhs, RT&& rhs) const
263 {
264 using CT = common_type_t<LT, RT>;
265 // ISSUE HERE - PRE C++20, no distinction made between strong_ordering, weak_ordering, and partial_ordering, because
266 // this counts on cooperation with various types and mechanismns like operator<=> = default which we don't have (and declared strong_ordering=int)
267 if (equal_to<CT>{}(forward<LT> (lhs), forward<RT> (rhs))) {
268 return strong_ordering::equal;
269 }
270 return less<CT>{}(forward<LT> (lhs), forward<RT> (rhs)) ? strong_ordering::less : strong_ordering::greater;
271 }
272 };
273#else
274 struct [[deprecated ("Since Stroika 3.0d1 - use std::compare_three_way")]] ThreeWayComparer {
275 template <typename LT, typename RT>
276 constexpr auto operator() (LT&& lhs, RT&& rhs) const
277 {
278 return compare_three_way{}(forward<LT> (lhs), forward<RT> (rhs));
279 }
280 };
281#endif
282 DISABLE_COMPILER_GCC_WARNING_START ("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
283 DISABLE_COMPILER_CLANG_WARNING_START ("clang diagnostic ignored \"-Wdeprecated-declarations\"");
284 DISABLE_COMPILER_MSC_WARNING_START (4996)
285 namespace Private_ {
286 template <typename ARG_T>
287 struct ExtractComparisonTraits_<ARG_T, ThreeWayComparer> {
288 static constexpr ComparisonRelationType kComparisonRelationKind = ComparisonRelationType::eThreeWayCompare;
289 };
290 }
291 DISABLE_COMPILER_MSC_WARNING_END (4996)
292 DISABLE_COMPILER_CLANG_WARNING_END ("clang diagnostic ignored \"-Wdeprecated-declarations\"");
293 DISABLE_COMPILER_GCC_WARNING_END ("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
294
295 constexpr std::strong_ordering kLess [[deprecated ("Since Stroika 3.0d1 - use std::strong_ordering")]] = std::strong_ordering::less;
296 constexpr std::strong_ordering kEqual [[deprecated ("Since Stroika 3.0d1 - use std::strong_ordering")]] = std::strong_ordering::equal;
297 constexpr std::strong_ordering kGreater [[deprecated ("Since Stroika 3.0d1 - use std::strong_ordering")]] = std::strong_ordering::greater;
298
299 template <typename FUNCTOR, typename FUNCTOR_ARG>
300 [[deprecated ("Since Stroika v3.0d1 - use IPotentiallyComparer ")]] constexpr bool IsPotentiallyComparerRelation ()
301 {
302 return IPotentiallyComparer<FUNCTOR, FUNCTOR_ARG>;
303 }
304 template <typename FUNCTOR>
305 [[deprecated ("Since Stroika v3.0d1 - use IPotentiallyComparer ")]] constexpr bool IsPotentiallyComparerRelation ()
306 {
307 if constexpr (FunctionTraits<FUNCTOR>::kArity == 2) {
308 using TRAITS = FunctionTraits<FUNCTOR>;
309 return same_as<typename TRAITS::template arg<0>::type, typename TRAITS::template arg<1>::type> and
310 IsPotentiallyComparerRelation<FUNCTOR, typename FunctionTraits<FUNCTOR>::template arg<0>::type> ();
311 }
312 else {
313 return false;
314 }
315 }
316 template <typename FUNCTOR>
317 [[deprecated ("Since Stroika v3.0d1 - use IPotentiallyComparer ")]] constexpr bool IsPotentiallyComparerRelation (const FUNCTOR& f)
318 {
319 return IsPotentiallyComparerRelation<FUNCTOR> ();
320 }
321 template <typename LT, typename RT>
322 [[deprecated ("Since Stroika 3.0d1 - use compare_three_way{} or <=>")]] constexpr strong_ordering ThreeWayCompare (LT&& lhs, RT&& rhs)
323 {
324 return compare_three_way{}(forward<LT> (lhs), forward<RT> (rhs));
325 }
326
327 template <typename COMPARER>
328 [[deprecated ("Since Stroika 3.0d1 - use IEqualsComparer")]] constexpr bool IsEqualsComparer ()
329 {
330 return ExtractComparisonTraits_v<int, std::remove_cvref_t<COMPARER>> == ComparisonRelationType::eEquals;
331 }
332 template <typename COMPARER, typename ARG_T>
333 [[deprecated ("Since Stroika 3.0d1 - use IEqualsComparer")]] constexpr bool IsEqualsComparer ()
334 {
335 if constexpr (not IsPotentiallyComparerRelation<COMPARER, ARG_T> ()) {
336 return false;
337 }
338 else {
339 return ExtractComparisonTraits_v<int, std::remove_cvref_t<COMPARER>> == ComparisonRelationType::eEquals;
340 }
341 }
342 template <typename COMPARER>
343 [[deprecated ("Since Stroika 3.0d1 - use IEqualsComparer")]] constexpr bool IsEqualsComparer (const COMPARER&)
344 {
345 return IsEqualsComparer<COMPARER> ();
346 }
347 template <typename COMPARER>
348 [[deprecated ("Since Stroika 3.0d1 - use IInOrderComparer")]] constexpr bool IsStrictInOrderComparer ()
349 {
350 return ExtractComparisonTraits_v<int, std::remove_cvref_t<COMPARER>> == ComparisonRelationType::eStrictInOrder;
351 }
352 template <typename COMPARER, typename ARG_T>
353 [[deprecated ("Since Stroika 3.0d1 - use IInOrderComparer")]] constexpr bool IsStrictInOrderComparer ()
354 {
355 if constexpr (not IsPotentiallyComparerRelation<COMPARER, ARG_T> ()) {
356 return false;
357 }
358 else {
359 return ExtractComparisonTraits_v<int, std::remove_cvref_t<COMPARER>> == ComparisonRelationType::eStrictInOrder;
360 }
361 }
362 template <typename COMPARER>
363 [[deprecated ("Since Stroika 3.0d1 - use IInOrderComparer")]] constexpr bool IsStrictInOrderComparer (const COMPARER&)
364 {
365 return ExtractComparisonTraits_v<int, std::remove_cvref_t<COMPARER>> == ComparisonRelationType::eStrictInOrder;
366 }
367
368 template <typename COMPARE_FUNCTION>
369 using ExtractComparisonTraits [[deprecated ("Since Stroika v3.0d1 - use ExtractComparisonTraits_v instead")]] =
370 Private_::ExtractComparisonTraits_<int, COMPARE_FUNCTION>;
371}
#define AssertNotReached()
Definition Assertions.h:355
constexpr Common::ComparisonRelationDeclaration< ComparisonRelationType::eStrictInOrder, remove_cvref_t< FUNCTOR > > DeclareInOrderComparer(FUNCTOR &&f)
DeclareInOrderComparer () marks a FUNCTOR (lambda or not) as being a FUNCTOR which compares for in-or...
Definition Compare.inl:44
constexpr Common::ComparisonRelationDeclaration< ComparisonRelationType::eEquals, remove_cvref_t< FUNCTOR > > DeclareEqualsComparer(FUNCTOR &&f)
DeclareEqualsComparer () marks a FUNCTOR (lambda or not) as being a FUNCTOR which compares for equali...
Definition Compare.inl:31
constexpr strong_ordering CompareResultNormalizer(FROM_INT_TYPE f)
Definition Compare.inl:226
constexpr strong_ordering ReverseCompareOrder(strong_ordering so)
Definition Compare.inl:242
STL namespace.
Extract the number of arguments, return type, and each individual argument type from a lambda or simp...
Definition Concepts.h:95