Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
operators.hpp
Go to the documentation of this file.
1// Copyright 2024, Toyota Motor Corporation
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_COMPARE_OPERATORS_HPP_
6#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_COMPARE_OPERATORS_HPP_
7
8// IWYU pragma: private, include "arene/base/compare.hpp"
9// IWYU pragma: friend "(arene/base(?!/tests)|stdlib/include/stdlib_detail)/.*"
10
11// parasoft-begin-suppress AUTOSAR-A7_1_5-a-2 "Trailing return syntax permitted by A7-1-5 Permit #1 v1.0.0"
12
13// parasoft-begin-suppress AUTOSAR-A16_2_2-a-2 "Arene Base aggregate headers permitted by A16-2-2 Permit #1"
14#include "arene/base/compare/compare_three_way.hpp"
15#include "arene/base/compare/strong_ordering.hpp"
16#include "arene/base/compiler_support/attributes.hpp"
17#include "arene/base/compiler_support/diagnostics.hpp"
18#include "arene/base/constraints/constraints.hpp"
19#include "arene/base/stdlib_choice/declval.hpp"
20#include "arene/base/stdlib_choice/enable_if.hpp"
21#include "arene/base/stdlib_choice/is_same.hpp"
22#include "arene/base/type_traits/comparison_traits.hpp"
23// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
24
25// parasoft-begin-suppress AUTOSAR-A11_3_1-a-2 "False positive: It is allowed to declare comparison operators as friend
26// functions"
27// parasoft-begin-suppress AUTOSAR-A13_5_5-b-2 "Mixed comparisons permitted by A13-5-5 Permit #1"
28
29namespace arene {
30namespace base {
31
32namespace operators_detail {
33/// @brief Helper class to define operator != in terms of the == operator with a left-hand operand of type @c LhsType
34/// and a right-hand operand of type @c RhsType
35/// @tparam LhsType The type of the left-hand operator parameter
36/// @tparam RhsType The type of the right-hand operator parameter
37template <typename LhsType, typename RhsType>
38class inequality_operator_mixin {
39 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
40 /// @brief Compare whether two objects are not equal.
41 ///
42 /// @param lhs Left-hand side of != operator.
43 /// @param rhs Right-hand side of != operator.
44 /// @return Return @c true if @c lhs is not equal to @c rhs, otherwise @c
45 /// false.
46 ARENE_NODISCARD friend constexpr auto operator!=(LhsType const& lhs, RhsType const& rhs) noexcept -> bool {
47 static_assert(is_nothrow_equality_comparable_v<LhsType const&, RhsType const&>, "operator == should be noexcept");
48 return !(lhs == rhs);
49 }
50 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
51
52 protected:
53 /// @brief Default constructor is protected
54 constexpr inequality_operator_mixin() noexcept = default;
55 /// @brief Default destructor is protected
56 ~inequality_operator_mixin() noexcept = default;
57 /// @brief Default copy constructor is protected
58 /// @param other The value to copy from
59 constexpr inequality_operator_mixin(inequality_operator_mixin const& other) noexcept = default;
60 /// @brief Default move constructor is protected
61 /// @param other The value to copy from
62 constexpr inequality_operator_mixin(inequality_operator_mixin&& other) noexcept = default;
63 /// @brief Default copy assignment is protected
64 /// @param other The value to copy from
65 constexpr auto operator=(inequality_operator_mixin const& other) & noexcept -> inequality_operator_mixin& = default;
66 /// @brief Default move assignment is protected
67 /// @param other The value to copy from
68 constexpr auto operator=(inequality_operator_mixin&& other) & noexcept -> inequality_operator_mixin& = default;
69};
70
71} // namespace operators_detail
72
73/// @brief Helper class that can be inherited from by a class to define the != operator in terms of the == operator
74/// defined by that class.
75///
76/// Requires that operator==(const Derived&, const Other&) is defined and does not throw exceptions
77///
78/// @tparam Derived The type of the derived class. The comparison operators provided take parameters of this type.
79/// @tparam Other The type of the other object to compare. The comparison operators provided take parameters of this
80/// type.
81///
82/// For example:
83/// @code {cpp}
84/// class MyClass : arene::base::full_equality_operators_from_basic_equality<MyClass>
85/// {
86/// ...
87/// // No need to explicitly define 'operator!=' here.
88/// friend bool operator==(const MyClass& a, const MyClass& b) noexcept;
89/// };
90/// @endcode
91// parasoft-begin-suppress AUTOSAR-A10_1_1-a-2 "False positive: all base classes are empty"
92template <typename Derived, typename Other = Derived>
93class full_equality_operators_from_basic_equality
94 : operators_detail::inequality_operator_mixin<Derived, Other>
95 , operators_detail::inequality_operator_mixin<Other, Derived> {
96 // parasoft-end-suppress
97 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
98 /// @brief Equality comparison operator for instances of @c Derived and @c Other.
99 /// @param lhs The first object being compared
100 /// @param rhs The second object being compared
101 /// @return bool Result of @c lhs==rhs
102 ARENE_NODISCARD friend constexpr auto operator==(Other const& lhs, Derived const& rhs) noexcept -> bool {
103 return rhs == lhs;
104 }
105 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
106
107 protected:
108 /// @brief Default constructor is protected
109 constexpr full_equality_operators_from_basic_equality() noexcept = default;
110 /// @brief Default destructor is protected
111 ~full_equality_operators_from_basic_equality() noexcept = default;
112 /// @brief Default copy constructor is protected
113 /// @param other The value to copy from
114 constexpr full_equality_operators_from_basic_equality(full_equality_operators_from_basic_equality const& other
115 ) noexcept = default;
116 /// @brief Default move constructor is protected
117 /// @param other The value to copy from
118 constexpr full_equality_operators_from_basic_equality(full_equality_operators_from_basic_equality&& other
119 ) noexcept = default;
120 /// @brief Default copy assignment is protected
121 /// @param other The value to copy from
122 constexpr auto operator=(full_equality_operators_from_basic_equality const& other) & noexcept
123 -> full_equality_operators_from_basic_equality& = default;
124 /// @brief Default move assignment is protected
125 /// @param other The value to copy from
126 constexpr auto operator=(full_equality_operators_from_basic_equality&& other) & noexcept
127 -> full_equality_operators_from_basic_equality& = default;
128};
129
130// @cond INTERNAL
131/// @brief Specialization for when @c Other is @c Derived.
132template <typename Derived>
133class full_equality_operators_from_basic_equality<Derived, Derived>
134 : operators_detail::inequality_operator_mixin<Derived, Derived> {
135 protected:
136 /// @brief Default constructor is protected
137 constexpr full_equality_operators_from_basic_equality() noexcept = default;
138 /// @brief Default destructor is protected
139 ~full_equality_operators_from_basic_equality() noexcept = default;
140 /// @brief Default copy constructor is protected
141 /// @param other The value to copy from
142 constexpr full_equality_operators_from_basic_equality(full_equality_operators_from_basic_equality const& other
143 ) noexcept = default;
144 /// @brief Default move constructor is protected
145 /// @param other The value to copy from
146 constexpr full_equality_operators_from_basic_equality(full_equality_operators_from_basic_equality&& other
147 ) noexcept = default;
148 /// @brief Default copy assignment is protected
149 /// @param other The value to copy from
150 constexpr auto operator=(full_equality_operators_from_basic_equality const& other) & noexcept
151 -> full_equality_operators_from_basic_equality& = default;
152 /// @brief Default move assignment is protected
153 /// @param other The value to copy from
154 constexpr auto operator=(full_equality_operators_from_basic_equality&& other) & noexcept
155 -> full_equality_operators_from_basic_equality& = default;
156};
157// @endcond
158
159namespace operators_detail {
160/// @brief Helper class to define <, >, <= and >= operators in terms of the @c LhsType::three_way_compare function with
161/// a left-hand operand of type @c LhsType and a right-hand operand of type @c RhsType
162/// @tparam LhsType The type of the left-hand operator parameter
163/// @tparam RhsType The type of the right-hand operator parameter
164template <typename LhsType, typename RhsType>
165class ordering_operators_from_three_way_mixin {
166 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
167 /// @brief Less-than comparison operator for instances of @c LhsType and @c RhsType.
168 /// @param lhs The first object being compared
169 /// @param rhs The second object being compared
170 /// @return @c True if @c lhs is less than @c rhs, @c false otherwise.
171 ARENE_NODISCARD friend constexpr auto operator<(LhsType const& lhs, RhsType const& rhs) noexcept -> bool {
172 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
173 // side-effects"
174 static_assert(
175 std::is_same<decltype(LhsType::three_way_compare(lhs, rhs)), strong_ordering>::value,
176 "LhsType class must provide three_way_compare function that "
177 "returns strong_ordering"
178 );
179 static_assert(noexcept(LhsType::three_way_compare(lhs, rhs)), "three_way_compare must be noexcept");
180 // parasoft-end-suppress CERT_C-PRE31-c-3
181 return LhsType::three_way_compare(lhs, rhs) == strong_ordering::less;
182 }
183 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
184
185 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
186 /// @brief Greater-than comparison operator for instances of @c LhsType and @c RhsType
187 /// @param lhs The first object being compared
188 /// @param rhs The second object being compared
189 /// @return @c True if @c lhs is greater than @c rhs, @c false otherwise.
190 ARENE_NODISCARD friend constexpr auto operator>(LhsType const& lhs, RhsType const& rhs) noexcept -> bool {
191 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
192 // side-effects"
193 static_assert(
194 std::is_same<decltype(LhsType::three_way_compare(lhs, rhs)), strong_ordering>::value,
195 "LhsType class must provide three_way_compare function that "
196 "returns strong_ordering"
197 );
198 static_assert(noexcept(LhsType::three_way_compare(lhs, rhs)), "three_way_compare must be noexcept");
199 // parasoft-end-suppress CERT_C-PRE31-c-3
200 return LhsType::three_way_compare(lhs, rhs) == strong_ordering::greater;
201 }
202 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
203
204 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
205 /// @brief Less-than-or-equal comparison operator for instances of @c LhsType and @c RhsType.
206 /// @param lhs The first object being compared
207 /// @param rhs The second object being compared
208 /// @return @c True if @c lhs is less than or equal to @c rhs, @c false
209 /// otherwise.
210 ARENE_NODISCARD friend constexpr auto operator<=(LhsType const& lhs, RhsType const& rhs) noexcept -> bool {
211 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
212 // side-effects"
213 static_assert(
214 std::is_same<decltype(LhsType::three_way_compare(lhs, rhs)), strong_ordering>::value,
215 "LhsType class must provide three_way_compare function that "
216 "returns strong_ordering"
217 );
218 static_assert(noexcept(LhsType::three_way_compare(lhs, rhs)), "three_way_compare must be noexcept");
219 // parasoft-end-suppress CERT_C-PRE31-c-3
220 auto const cmp_res = LhsType::three_way_compare(lhs, rhs);
221 return cmp_res == strong_ordering::less || cmp_res == strong_ordering::equal;
222 }
223 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
224
225 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
226 /// @brief Greater-than-or-equal comparison operator for instances of @c LhsType and
227 /// @c RhsType.
228 /// @param lhs The first object being compared
229 /// @param rhs The second object being compared
230 /// @return true if @c LhsType::three_way_compare(lhs,rhs) returns @c strong_ordering::greater or @c
231 /// strong_ordering::equal .
232 /// @return false if @c LhsType::three_way_compare(lhs,rhs) returns @c strong_ordering::less .
233 /// otherwise.
234 ARENE_NODISCARD friend constexpr auto operator>=(LhsType const& lhs, RhsType const& rhs) noexcept -> bool {
235 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
236 // side-effects"
237 static_assert(
238 std::is_same<decltype(LhsType::three_way_compare(lhs, rhs)), strong_ordering>::value,
239 "LhsType class must provide three_way_compare function that "
240 "returns strong_ordering"
241 );
242 static_assert(noexcept(LhsType::three_way_compare(lhs, rhs)), "three_way_compare must be noexcept");
243 // parasoft-end-suppress CERT_C-PRE31-c-3
244 auto const cmp_res = LhsType::three_way_compare(lhs, rhs);
245 return cmp_res == strong_ordering::greater || cmp_res == strong_ordering::equal;
246 }
247 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
248
249 protected:
250 /// @brief Default constructor is protected
251 constexpr ordering_operators_from_three_way_mixin() noexcept = default;
252 /// @brief Default destructor is protected
253 ~ordering_operators_from_three_way_mixin() noexcept = default;
254 /// @brief Default copy constructor is protected
255 /// @param other The source object
256 constexpr ordering_operators_from_three_way_mixin(ordering_operators_from_three_way_mixin const& other
257 ) noexcept = default;
258 /// @brief Default move constructor is protected
259 /// @param other The source object
260 constexpr ordering_operators_from_three_way_mixin(ordering_operators_from_three_way_mixin&& other) noexcept = default;
261 /// @brief Default copy assignment is protected
262 /// @param other The source object
263 constexpr auto operator=(ordering_operators_from_three_way_mixin const& other) & noexcept
264 -> ordering_operators_from_three_way_mixin& = default;
265 /// @brief Default move assignment is protected
266 /// @param other The source object
267 constexpr auto operator=(ordering_operators_from_three_way_mixin&& other) & noexcept
268 -> ordering_operators_from_three_way_mixin& = default;
269};
270} // namespace operators_detail
271
272/// @brief Helper class that can be inherited from by a class to define the @c <, @c >, @c <= and @c >= comparison
273/// operators in terms of a @c three_way_compare function provided by the Derived class, and define the @c != operator
274/// in terms of the @c == operator.
275///
276/// Requires that the derived class provides a @c static member function @c three_way_compare that accepts a <c>const
277/// Derived&</c> and a <c>const Other&</c>, and returns a @c strong_ordering value indicating whether the first is less
278/// than, equal to or greater than the second. This @c three_way_compare functions must not throw exceptions.
279///
280/// Requires that operator==(const Derived&, const Other&) is defined and does not throw exceptions
281///
282/// @tparam Derived The type of the derived class. The comparison operators provided take parameters of this type.
283/// @tparam Other The type of the other object to compare. The comparison operators provided take parameters of this
284/// type.
285///
286/// For example:
287/// @code {cpp}
288/// class MyClass :
289/// arene::base::full_ordering_operators_from_three_way_compare_and_equals<MyClass> {
290/// ...
291/// friend arene::base::string_ordering three_way_compare(
292/// const MyClass& a, const MyClass& b) noexcept;
293/// friend bool operator==(const MyClass& a, const MyClass& b) noexcept;
294/// };
295/// @endcode
296///
297/// @deprecated Prefer arene::base::generic_ordering_from_three_way_compare
298// parasoft-begin-suppress AUTOSAR-A10_1_1-a-2 "False positive: all base classes are empty"
299template <typename Derived, typename Other = Derived>
300class ARENE_DEPRECATED_WITH("Use generic_ordering_from_three_way_compare instead"
304 // parasoft-end-suppress
305 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
306 /// @brief Less-than comparison operator for instances of @c Derived and @c Other.
307 /// @param lhs The first object being compared
308 /// @param rhs The second object being compared
309 /// @return bool The result of @c rhs>lhs .
310 ARENE_NODISCARD friend constexpr auto operator<(Other const& lhs, Derived const& rhs) noexcept -> bool {
311 return rhs > lhs;
312 }
313 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
314
315 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
316 /// @brief Greater-than comparison operator for instances of @c Derived and @c Other.
317 /// @param lhs The first object being compared
318 /// @param rhs The second object being compared
319 /// @return bool The result of @c rhs<lhs .
320 ARENE_NODISCARD friend constexpr auto operator>(Other const& lhs, Derived const& rhs) noexcept -> bool {
321 return rhs < lhs;
322 }
323 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
324
325 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
326 /// @brief Less-than-or-equal comparison operator for instances of @c Derived and @c
327 /// Other.
328 /// @param lhs The first object being compared
329 /// @param rhs The second object being compared
330 /// @return bool The result of @c rhs>=lhs .
331 ARENE_NODISCARD friend constexpr auto operator<=(Other const& lhs, Derived const& rhs) noexcept -> bool {
332 return rhs >= lhs;
333 }
334 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
335
336 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
337 /// @brief Greater-than-or-equal comparison operator for instances of @c Derived and
338 /// @c Other.
339 /// @param lhs The first object being compared
340 /// @param rhs The second object being compared
341 /// @return bool The result of @c rhs<=lhs .
342 ARENE_NODISCARD friend constexpr auto operator>=(Other const& lhs, Derived const& rhs) noexcept -> bool {
343 return rhs <= lhs;
344 }
345 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
346
347 protected:
348 /// @brief Default constructor is protected
350 /// @brief Default destructor is protected
352 /// @brief Default copy constructor is protected
353 /// @param other The source object
356 ) noexcept = default;
357 /// @brief Default move constructor is protected
358 /// @param other The source object
361 ) noexcept = default;
362 /// @brief Default copy assignment is protected
363 /// @param other The source object
366 /// @brief Default move assignment is protected
367 /// @param other The source object
370};
371
372// @cond INTERNAL
373ARENE_IGNORE_START();
374ARENE_IGNORE_ALL("-Wdeprecated-declarations", "We still want to specialize the deprecated classes");
375/// @brief Specialization for the case that @c Other is @c Derived
376// parasoft-begin-suppress AUTOSAR-A10_1_1-a-2 "False positive: all base classes are empty"
377template <typename Derived>
378class full_ordering_operators_from_three_way_compare_and_equals<Derived, Derived>
379 : full_equality_operators_from_basic_equality<Derived>
380 , operators_detail::ordering_operators_from_three_way_mixin<Derived, Derived> {
381 // parasoft-end-suppress
382 protected:
383 /// @brief Default constructor is protected
384 constexpr full_ordering_operators_from_three_way_compare_and_equals() noexcept = default;
385 /// @brief Default destructor is protected
386 ~full_ordering_operators_from_three_way_compare_and_equals() noexcept = default;
387 /// @brief Default copy constructor is protected
388 /// @param other The source object
389 constexpr full_ordering_operators_from_three_way_compare_and_equals(
390 full_ordering_operators_from_three_way_compare_and_equals const& other
391 ) noexcept = default;
392 /// @brief Default move constructor is protected
393 /// @param other The source object
394 constexpr full_ordering_operators_from_three_way_compare_and_equals(
395 full_ordering_operators_from_three_way_compare_and_equals&& other
396 ) noexcept = default;
397 /// @brief Default copy assignment is protected
398 /// @param other The source object
399 constexpr auto operator=(full_ordering_operators_from_three_way_compare_and_equals const& other) & noexcept
400 -> full_ordering_operators_from_three_way_compare_and_equals& = default;
401 /// @brief Default move assignment is protected
402 /// @param other The source object
403 constexpr auto operator=(full_ordering_operators_from_three_way_compare_and_equals&& other) & noexcept
404 -> full_ordering_operators_from_three_way_compare_and_equals& = default;
405};
406ARENE_IGNORE_END();
407// @endcond
408
409ARENE_IGNORE_START();
411 "-Wdeprecated-declarations",
412 "We still want to use the deprecated class in this other deprecated class"
413);
414/// @brief Helper class that can be inherited from by a class to define the @c
415/// <, @c >, @c <=, @c >=, @c ==, and @c != comparison operators in terms of a
416/// @c three_way_compare function provided by the Derived class.
417///
418/// Requires that the derived class provides a @c static member function @c three_way_compare that accepts two <c>const
419/// Derived&</c> and returns a @c strong_ordering value indicating whether the first is less than, equal to or greater
420/// than the second. This @c three_way_compare functions must not throw exceptions.
421///
422/// @tparam Derived The type of the derived class. The comparison operators
423/// provided take parameters of this type.
424///
425/// For example:
426/// @code {cpp}
427/// class MyClass :
428/// arene::base::full_ordering_operators_from_three_way_compare<MyClass> {
429/// ...
430/// friend arene::base::string_ordering three_way_compare(
431/// const MyClass& a, const MyClass& b) noexcept;
432/// };
433/// @endcode
434///
435/// @deprecated Prefer arene::base::generic_ordering_from_three_way_compare
436template <typename Derived, typename Other = Derived>
437class ARENE_DEPRECATED_WITH("Use generic_ordering_from_three_way_compare instead"
440 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
441 /// @brief Equality comparison operator for instances of @c Derived and @c Other.
442 /// @param lhs The first object being compared
443 /// @param rhs The second object being compared
444 /// @return @c True if @c lhs is equal to @c rhs, @c false otherwise.
445 ARENE_NODISCARD friend constexpr auto operator==(Derived const& lhs, Other const& rhs) noexcept -> bool {
446 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
447 // side-effects"
448 static_assert(
450 "Derived class must provide three_way_compare function that "
451 "returns strong_ordering"
452 );
453 static_assert(noexcept(Derived::three_way_compare(lhs, rhs)), "three_way_compare must be noexcept");
454 // parasoft-end-suppress CERT_C-PRE31-c-3
456 }
457 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
458
459 protected:
460 /// @brief Default constructor is protected
461 constexpr full_ordering_operators_from_three_way_compare() noexcept = default;
462 /// @brief Default destructor is protected
464 /// @brief Default copy constructor is protected
465 /// @param other The source object
467 ) noexcept = default;
468 /// @brief Default move constructor is protected
469 /// @param other The source object
471 ) noexcept = default;
472 /// @brief Default copy assignment is protected
473 /// @param other The source object
474 constexpr auto operator=(full_ordering_operators_from_three_way_compare const& other) & noexcept
476 /// @brief Default move assignment is protected
477 /// @param other The source object
480};
481ARENE_IGNORE_END();
482
483namespace operators_detail {
484/// @brief Helper class to define >, <= and >= operators in terms of the < operator with a left-hand operand of type @c
485/// LhsType and a right-hand operand of type @c RhsType
486/// @tparam LhsType The type of the left-hand operator parameter
487/// @tparam RhsType The type of the right-hand operator parameter
488template <typename LhsType, typename RhsType>
489class ordering_operators_from_less_than_mixin {
490 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
491 /// @brief Greater-than comparison operator for instances of @c LhsType and @c RhsType
492 /// @param lhs The first object being compared
493 /// @param rhs The second object being compared
494 /// @return @c True if @c lhs is greater than @c rhs, @c false otherwise.
495 ARENE_NODISCARD friend constexpr auto operator>(LhsType const& lhs, RhsType const& rhs) noexcept -> bool {
496 static_assert(is_nothrow_less_than_comparable_v<RhsType const&, LhsType const&>, "rhs < lhs should be noexcept");
497 return static_cast<bool>(rhs < lhs);
498 }
499 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
500
501 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
502 /// @brief Less-than-or-equal comparison operator for instances of @c LhsType and @c
503 /// RhsType.
504 /// @param lhs The first object being compared
505 /// @param rhs The second object being compared
506 /// @return @c True if @c lhs is less than or equal to @c rhs, @c false
507 /// otherwise.
508 ARENE_NODISCARD friend constexpr auto operator<=(LhsType const& lhs, RhsType const& rhs) noexcept -> bool {
509 static_assert(is_nothrow_less_than_comparable_v<RhsType const&, LhsType const&>, "rhs < lhs should be noexcept");
510 return !static_cast<bool>(rhs < lhs);
511 }
512 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
513
514 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
515 /// @brief Greater-than-or-equal comparison operator for instances of @c LhsType and
516 /// @c RhsType.
517 /// @param lhs The first object being compared
518 /// @param rhs The second object being compared
519 /// @return @c True if @c lhs is greater than or equal to @c rhs, @c false
520 /// otherwise.
521 ARENE_NODISCARD friend constexpr auto operator>=(LhsType const& lhs, RhsType const& rhs) noexcept -> bool {
522 static_assert(is_nothrow_less_than_comparable_v<RhsType const&, LhsType const&>, "rhs < lhs should be noexcept");
523 return !static_cast<bool>(lhs < rhs);
524 }
525 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
526
527 protected:
528 /// @brief Default constructor is protected
529 constexpr ordering_operators_from_less_than_mixin() noexcept = default;
530 /// @brief Default destructor is protected
531 ~ordering_operators_from_less_than_mixin() noexcept = default;
532 /// @brief Default copy constructor is protected
533 /// @param other The source object
534 constexpr ordering_operators_from_less_than_mixin(ordering_operators_from_less_than_mixin const& other
535 ) noexcept = default;
536 /// @brief Default move constructor is protected
537 /// @param other The source object
538 constexpr ordering_operators_from_less_than_mixin(ordering_operators_from_less_than_mixin&& other) noexcept = default;
539 /// @brief Default copy assignment is protected
540 /// @param other The source object
541 constexpr auto operator=(ordering_operators_from_less_than_mixin const& other) & noexcept
542 -> ordering_operators_from_less_than_mixin& = default;
543 /// @brief Default move assignment is protected
544 /// @param other The source object
545 constexpr auto operator=(ordering_operators_from_less_than_mixin&& other) & noexcept
546 -> ordering_operators_from_less_than_mixin& = default;
547};
548} // namespace operators_detail
549
550/// @brief Helper class that can be inherited from by a class to define the >, <=, >=, != operators in terms of a <
551/// operator and == operator that the derived class provides.
552///
553/// The derived class is required to provide:
554/// - operator<(const Derived&, const Other&)
555/// - operator<(const Other&, const Derived&)
556/// - operator==(const Derived&, const Other&)
557///
558/// This class defines the following operators in terms of those:
559/// - operator>(const Derived&, const Other&)
560/// - operator<=(const Derived&, const Other&)
561/// - operator>=(const Derived&, const Other&)
562/// - operator!=(const Derived&, const Other&)
563/// - operator>(const Other&, const Derived&)
564/// - operator<=(const Other&, const Derived&)
565/// - operator>=(const Other&, const Derived&)
566/// - operator==(const Other&, const Derived&)
567/// - operator!=(const Other&, const Derived&)
568///
569/// For example:
570/// @code {cpp}
571/// class MyString :
572/// arene::base::full_ordering_operators_from_less_than_and_equals<MyString, const
573/// char*> {
574/// ...
575/// // Only need to define less-than and equals. Others defined in terms of
576/// this.
577/// friend bool operator<(const MyString& a, const char* b) noexcept;
578/// friend bool operator<(const char* a, const MyString& b) noexcept;
579/// friend bool operator==(const MyString& a, const char* b) noexcept;
580/// };
581/// @endcode
582// parasoft-begin-suppress AUTOSAR-A10_1_1-a-2 "False positive: all base classes are empty"
583template <typename Derived, typename Other = Derived>
584class full_ordering_operators_from_less_than_and_equals
585 : operators_detail::ordering_operators_from_less_than_mixin<Derived, Other>
586 , operators_detail::ordering_operators_from_less_than_mixin<Other, Derived>
587 , full_equality_operators_from_basic_equality<Derived, Other> {
588 // parasoft-end-suppress
589 protected:
590 /// @brief Default constructor is protected
591 constexpr full_ordering_operators_from_less_than_and_equals() noexcept = default;
592 /// @brief Default destructor is protected
593 ~full_ordering_operators_from_less_than_and_equals() noexcept = default;
594 /// @brief Default copy constructor is protected
595 /// @param other The source object
596 constexpr full_ordering_operators_from_less_than_and_equals(
597 full_ordering_operators_from_less_than_and_equals const& other
598 ) noexcept = default;
599 /// @brief Default move constructor is protected
600 /// @param other The source object
601 constexpr full_ordering_operators_from_less_than_and_equals(full_ordering_operators_from_less_than_and_equals&& other
602 ) noexcept = default;
603 /// @brief Default copy assignment is protected
604 /// @param other The source object
605 constexpr auto operator=(full_ordering_operators_from_less_than_and_equals const& other) & noexcept
606 -> full_ordering_operators_from_less_than_and_equals& = default;
607 /// @brief Default move assignment is protected
608 /// @param other The source object
609 constexpr auto operator=(full_ordering_operators_from_less_than_and_equals&& other) & noexcept
610 -> full_ordering_operators_from_less_than_and_equals& = default;
611};
612
613// @cond INTERNAL
614/// @brief Specialization for the case that @c Other is @c Derived
615template <typename Derived>
616class full_ordering_operators_from_less_than_and_equals<Derived, Derived>
617 : operators_detail::ordering_operators_from_less_than_mixin<Derived, Derived>
618 , full_equality_operators_from_basic_equality<Derived> {
619 protected:
620 /// @brief Default constructor is protected
621 constexpr full_ordering_operators_from_less_than_and_equals() noexcept = default;
622 /// @brief Default destructor is protected
623 ~full_ordering_operators_from_less_than_and_equals() noexcept = default;
624 /// @brief Default copy constructor is protected
625 /// @param other The source object
626 constexpr full_ordering_operators_from_less_than_and_equals(
627 full_ordering_operators_from_less_than_and_equals const& other
628 ) noexcept = default;
629 /// @brief Default move constructor is protected
630 /// @param other The source object
631 constexpr full_ordering_operators_from_less_than_and_equals(full_ordering_operators_from_less_than_and_equals&& other
632 ) noexcept = default;
633 /// @brief Default copy assignment is protected
634 /// @param other The source object
635 constexpr auto operator=(full_ordering_operators_from_less_than_and_equals const& other) & noexcept
636 -> full_ordering_operators_from_less_than_and_equals& = default;
637 /// @brief Default move assignment is protected
638 /// @param other The source object
639 constexpr auto operator=(full_ordering_operators_from_less_than_and_equals&& other) & noexcept
640 -> full_ordering_operators_from_less_than_and_equals& = default;
641};
642// @endcond
643
644/// @brief Helper class that can be inherited from by a class to define the >, <=, >=, == and != operators in terms of a
645/// < operator that the derived class provides.
646///
647/// The derived class is required to provide:
648/// - operator<(const Derived&, const Other&)
649/// - operator<(const Other&, const Derived&)
650///
651/// This class defines the following operators in terms of those:
652/// - operator>(const Derived&, const Other&)
653/// - operator<=(const Derived&, const Other&)
654/// - operator>=(const Derived&, const Other&)
655/// - operator==(const Derived&, const Other&)
656/// - operator!=(const Derived&, const Other&)
657/// - operator>(const Other&, const Derived&)
658/// - operator<=(const Other&, const Derived&)
659/// - operator>=(const Other&, const Derived&)
660/// - operator==(const Other&, const Derived&)
661/// - operator!=(const Other&, const Derived&)
662///
663/// For example:
664/// @code {cpp}
665/// class MyString : arene::base::full_ordering_operators_from_less_than<MyString,
666/// const char*> {
667/// ...
668/// // Only need to define less-than. Others defined in terms of this.
669/// friend bool operator<(const MyString& a, const char* b) noexcept;
670/// friend bool operator<(const char* a, const MyString& b) noexcept;
671/// };
672/// @endcode
673template <typename Derived, typename Other = Derived>
674class full_ordering_operators_from_less_than : full_ordering_operators_from_less_than_and_equals<Derived, Other> {
675 // parasoft-begin-suppress AUTOSAR-A0_1_3-a-2 "False positive: This is a namespace scope function"
676 /// @brief Greater-than-or-equal comparison operator for instances of @c LhsType and
677 /// @c RhsType.
678 /// @param lhs The first object being compared
679 /// @param rhs The second object being compared
680 /// @return @c True if @c lhs is greater than or equal to @c rhs, @c false
681 /// otherwise.
682 ARENE_NODISCARD friend constexpr auto operator==(Derived const& lhs, Other const& rhs) noexcept -> bool {
683 static_assert(is_nothrow_less_than_comparable_v<Derived const&, Other const&>, "lhs < rhs should be noexcept");
684 static_assert(is_nothrow_less_than_comparable_v<Other const&, Derived const&>, "rhs < lhs should be noexcept");
685 return !static_cast<bool>(lhs < rhs) && !static_cast<bool>(rhs < lhs);
686 }
687 // parasoft-end-suppress AUTOSAR-A0_1_3-a-2
688};
689
690/// @brief An enumeration used for the return value of @c fast_inequality_check functions to indicate if two values are
691/// definitely not equal, or may be equal or not. This is used in generic implementations of @c operator== and @c
692/// operator!= to avoid comparing for ordering when only equality is required.
693enum class inequality_heuristic : bool {
694 ///@brief The two values checked are definitely not equal to each other
695 definitely_not_equal,
696 ///@brief The values checked may or may not be equal to each other; a more detailed check is required
697 may_be_equal_or_not_equal
698};
699
700/// @brief Type trait to check if an instance of type @c T can be compared to an instance of type @c U with a static
701/// @c fast_inequality_check member function that returns @c inequality_heuristic.
702/// @tparam T The type of the lhs
703/// @tparam U The type of the rhs. Defaults to @c T
704/// @return true If @c T::fast_inequality_check(T,U) is defined and returns @c inequality_heuristic.
705/// @return false Otherwise.
706template <typename T, typename U = T, typename = constraints<>>
707extern constexpr bool has_fast_inequality_check_v = false;
708
709/// @brief Specialization for the case that @c T and @c U can be compared.
710template <typename T, typename U>
711extern constexpr bool has_fast_inequality_check_v<
712 T,
713 U,
715 decltype(T::fast_inequality_check(std::declval<T const&>(), std::declval<U const&>())),
716 inequality_heuristic>::value>>> = true;
717
718/// @brief Helper class that can be inherited from by a class to define the relational comparison operators in terms of
719/// a @c three_way_compare function provided by the @c Derived class, and an optional fast-inequality check heuristic.
720///
721/// Generates the @c <, @c >, @c <=, @c >=, @c ==, and @c != comparison operators from a possibly overloaded @c static
722/// member function @c three_way_compare in the @c Derived class that accepts a <c>const Derived&</c> as the first
723/// argument and any other type as the second argument, and returns a @c strong_ordering value indicating whether the
724/// first is less than, equal to or greater than the second. These @c three_way_compare functions must not throw
725/// exceptions.
726///
727/// The derived class can optionally provide a @c static member function @c fast_inequality_check that accepts a
728/// <c>const Derived&</c> as the first argument and any other type as the second argument, and returns a @c
729/// inequality_heuristic value indicating whether the first is definitely not equal to the second, or may or may not be
730/// equal to the second. These @c fast_inequality_check functions must not throw exceptions. The generated @c operator==
731/// and @c operator!= overloads will invoke @c fast_inequality_check prior to @c three_way_compare if there is an
732/// overload provided that accepts the given types.
733///
734/// @tparam Derived The type of the derived class. The comparison operators provided take parameters of this type.
735///
736/// For example:
737/// @snippet docs/examples/ordering_examples.cpp string_like_generic_example
738///
739/// Here, @c MyClass has comparison operators for comparing instances of @c MyClass with each other, or with @c
740/// OtherClass, or with @c YetAnotherClass. Equality comparisons with @c OtherClass will use @c fast_inequality_check to
741/// avoid calling a potentially expensive @c three_way_compare for instances that are definitely not equal. e.g. this
742/// may be used to check the size of a container, and avoid doing elementwise comparisons when ordering is not required.
743template <typename Derived>
744class generic_ordering_from_three_way_compare {
745 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
746 /// @brief Less-than comparison operator for instances of @c Derived with @c Other.
747 /// @tparam Self the type of the @c Derived object to compare, used for constraints
748 /// @tparam Other the type of the object to compare to
749 /// @param lhs The instance of @c Derived to compare
750 /// @param rhs The instance of @c Other to compare
751 /// @return bool @c true if @c lhs is less than @c rhs, @c false otherwise
752 /// @pre @c Derived::three_way_compare(lhs,rhs) is well-formed
753 template <
754 typename Self,
755 typename Other,
756 constraints<
757 std::enable_if_t<std::is_same<Self, Derived>::value>,
758 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>> = nullptr>
759 ARENE_NODISCARD friend constexpr auto operator<(Self const& lhs, Other const& rhs) noexcept -> bool {
760 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
761 // side-effects"
762 static_assert(noexcept(Derived::three_way_compare(lhs, rhs)), "three_way_compare must be noexcept");
763 // parasoft-end-suppress CERT_C-PRE31-c-3
764 return Derived::three_way_compare(lhs, rhs) == strong_ordering::less;
765 }
766 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
767
768 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
769 /// @brief Less-than comparison operator for instances of @c Derived with @c Other.
770 /// @tparam Self the type of the @c Derived object to compare, used for constraints
771 /// @tparam Other The type of the object to compare to
772 /// @param lhs The instance of @c Other to compare
773 /// @param rhs The instance of @c Derived to compare
774 /// @return bool @c true if @c lhs is less than @c rhs, @c false otherwise
775 /// @pre @c Derived::three_way_compare(rhs,lhs) is well-formed
776 template <
777 typename Self,
778 typename Other,
779 constraints<
780 std::enable_if_t<std::is_same<Self, Derived>::value>,
781 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>,
782 std::enable_if_t<!is_three_way_comparable_v<Other, Derived>>> = nullptr>
783 ARENE_NODISCARD friend constexpr auto operator<(Other const& lhs, Self const& rhs) noexcept -> bool {
784 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
785 // side-effects"
786 static_assert(noexcept(Derived::three_way_compare(rhs, lhs)), "three_way_compare must be noexcept");
787 // parasoft-end-suppress CERT_C-PRE31-c-3
788 return Derived::three_way_compare(rhs, lhs) == strong_ordering::greater;
789 }
790 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
791
792 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
793 /// @brief Greater-than comparison operator for instances of @c Derived with @c Other.
794 /// @tparam Self the type of the @c Derived object to compare, used for constraints
795 /// @tparam Other the type of the object to compare to
796 /// @param lhs The instance of @c Derived to compare
797 /// @param rhs The instance of @c Other to compare
798 /// @return bool @c true if @c lhs is greater than @c rhs, @c false otherwise
799 /// @pre @c Derived::three_way_compare(lhs,rhs) is well-formed
800 template <
801 typename Self,
802 typename Other,
803 constraints<
804 std::enable_if_t<std::is_same<Self, Derived>::value>,
805 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>> = nullptr>
806 ARENE_NODISCARD friend constexpr auto operator>(Self const& lhs, Other const& rhs) noexcept -> bool {
807 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
808 // side-effects"
809 static_assert(noexcept(Derived::three_way_compare(lhs, rhs)), "three_way_compare must be noexcept");
810 // parasoft-end-suppress CERT_C-PRE31-c-3
811 return Derived::three_way_compare(lhs, rhs) == strong_ordering::greater;
812 }
813 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
814
815 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
816 /// @brief Greater-than comparison operator for instances of @c Derived with @c Other.
817 /// @tparam Self the type of the @c Derived object to compare, used for constraints
818 /// @tparam Other the type of the object to compare to
819 /// @param lhs The instance of @c Other to compare
820 /// @param rhs The instance of @c Derived to compare
821 /// @return bool @c true if @c lhs is greater than @c rhs, @c false otherwise
822 /// @pre @c Derived::three_way_compare(rhs,lhs) is well-formed
823 template <
824 typename Self,
825 typename Other,
826 constraints<
827 std::enable_if_t<std::is_same<Self, Derived>::value>,
828 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>,
829 std::enable_if_t<!is_three_way_comparable_v<Other, Derived>>> = nullptr>
830 ARENE_NODISCARD friend constexpr auto operator>(Other const& lhs, Self const& rhs) noexcept -> bool {
831 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
832 // side-effects"
833 static_assert(noexcept(Derived::three_way_compare(rhs, lhs)), "three_way_compare must be noexcept");
834 // parasoft-end-suppress CERT_C-PRE31-c-3
835 return Derived::three_way_compare(rhs, lhs) == strong_ordering::less;
836 }
837 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
838
839 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
840 /// @brief Less-than-or-equal comparison operator for instances of @c Derived with @c Other.
841 /// @tparam Self the type of the @c Derived object to compare, used for constraints
842 /// @tparam Other the type of the object to compare to
843 /// @param lhs The instance of @c Derived to compare
844 /// @param rhs The instance of @c Other to compare
845 /// @return bool @c true if @c lhs is less than or equal to @c rhs, @c false otherwise
846 /// @pre @c Derived::three_way_compare(lhs,rhs) is well-formed
847 template <
848 typename Self,
849 typename Other,
850 constraints<
851 std::enable_if_t<std::is_same<Self, Derived>::value>,
852 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>> = nullptr>
853 ARENE_NODISCARD friend constexpr auto operator<=(Self const& lhs, Other const& rhs) noexcept -> bool {
854 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
855 // side-effects"
856 static_assert(noexcept(Derived::three_way_compare(lhs, rhs)), "three_way_compare must be noexcept");
857 // parasoft-end-suppress CERT_C-PRE31-c-3
858 return Derived::three_way_compare(lhs, rhs) != strong_ordering::greater;
859 }
860 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
861
862 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
863 /// @brief Less-than-or-equal comparison operator for instances of @c Derived with @c Other.
864 /// @tparam Self the type of the @c Derived object to compare, used for constraints
865 /// @tparam Other the type of the object to compare to
866 /// @param lhs The instance of @c Other to compare
867 /// @param rhs The instance of @c Derived to compare
868 /// @return bool @c true if @c lhs is less than or equal to @c rhs, @c false otherwise
869 /// @pre @c Derived::three_way_compare(rhs,lhs) is well-formed
870 template <
871 typename Self,
872 typename Other,
873 constraints<
874 std::enable_if_t<std::is_same<Self, Derived>::value>,
875 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>,
876 std::enable_if_t<!is_three_way_comparable_v<Other, Derived>>> = nullptr>
877 ARENE_NODISCARD friend constexpr auto operator<=(Other const& lhs, Self const& rhs) noexcept -> bool {
878 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
879 // side-effects"
880 static_assert(noexcept(Derived::three_way_compare(rhs, lhs)), "three_way_compare must be noexcept");
881 // parasoft-end-suppress CERT_C-PRE31-c-3
882 return Derived::three_way_compare(rhs, lhs) != strong_ordering::less;
883 }
884 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
885
886 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
887 /// @brief Greater-than-or-equal comparison operator for instances of @c Derived with @c Other.
888 /// @tparam Self the type of the @c Derived object to compare, used for constraints
889 /// @tparam Other the type of the object to compare to
890 /// @param lhs The instance of @c Derived to compare
891 /// @param rhs The instance of @c Other to compare
892 /// @return bool @c true if @c lhs is greater than or equal to @c rhs, @c false otherwise
893 /// @pre @c Derived::three_way_compare(lhs,rhs) is well-formed
894 template <
895 typename Self,
896 typename Other,
897 constraints<
898 std::enable_if_t<std::is_same<Self, Derived>::value>,
899 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>> = nullptr>
900 ARENE_NODISCARD friend constexpr auto operator>=(Self const& lhs, Other const& rhs) noexcept -> bool {
901 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
902 // side-effects"
903 static_assert(noexcept(Derived::three_way_compare(lhs, rhs)), "three_way_compare must be noexcept");
904 // parasoft-end-suppress CERT_C-PRE31-c-3
905 return Derived::three_way_compare(lhs, rhs) != strong_ordering::less;
906 }
907 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
908
909 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
910 /// @brief Greater-than-or-equal comparison operator for instances of @c Derived with @c Other.
911 /// @tparam Self the type of the @c Derived object to compare, used for constraints
912 /// @tparam Other the type of the object to compare to
913 /// @param lhs The instance of @c Other to compare
914 /// @param rhs The instance of @c Derived to compare
915 /// @return bool @c true if @c lhs is greater than or equal to @c rhs, @c false otherwise
916 /// @pre @c Derived::three_way_compare(rhs,lhs) is well-formed
917 template <
918 typename Self,
919 typename Other,
920 constraints<
921 std::enable_if_t<std::is_same<Self, Derived>::value>,
922 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>,
923 std::enable_if_t<!is_three_way_comparable_v<Other, Derived>>> = nullptr>
924 ARENE_NODISCARD friend constexpr auto operator>=(Other const& lhs, Self const& rhs) noexcept -> bool {
925 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
926 // side-effects"
927 static_assert(noexcept(Derived::three_way_compare(rhs, lhs)), "three_way_compare must be noexcept");
928 // parasoft-end-suppress CERT_C-PRE31-c-3
929 return Derived::three_way_compare(rhs, lhs) != strong_ordering::greater;
930 }
931 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
932
933 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
934 /// @brief Equality comparison operator for instances of @c Derived with @c Other.
935 /// @tparam Self the type of the @c Derived object to compare, used for constraints
936 /// @tparam Other the type of the object to compare to
937 /// @param lhs The instance of @c Derived to compare
938 /// @param rhs The instance of @c Other to compare
939 /// @return bool @c true if @c lhs is equal to @c rhs, @c false otherwise
940 /// @pre @c Derived::three_way_compare(lhs,rhs) is well-formed
941 template <
942 typename Self,
943 typename Other,
944 constraints<
945 std::enable_if_t<std::is_same<Self, Derived>::value>,
946 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>,
947 std::enable_if_t<!has_fast_inequality_check_v<Derived, Other>>> = nullptr>
948 ARENE_NODISCARD friend constexpr auto operator==(Self const& lhs, Other const& rhs) noexcept -> bool {
949 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
950 // side-effects"
951 static_assert(noexcept(Derived::three_way_compare(lhs, rhs)), "three_way_compare must be noexcept");
952 // parasoft-end-suppress CERT_C-PRE31-c-3
953 return Derived::three_way_compare(lhs, rhs) == strong_ordering::equal;
954 }
955 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
956
957 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
958 /// @brief Equality comparison operator for instances of @c Derived with @c Other.
959 /// @tparam Self the type of the @c Derived object to compare, used for constraints
960 /// @tparam Other the type of the object to compare to
961 /// @param lhs The instance of @c Derived to compare
962 /// @param rhs The instance of @c Other to compare
963 /// @return bool @c true if @c lhs is equal to @c rhs, @c false otherwise
964 /// @pre @c Derived::three_way_compare(lhs,rhs) is well-formed
965 template <
966 typename Self,
967 typename Other,
968 constraints<
969 std::enable_if_t<std::is_same<Self, Derived>::value>,
970 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>,
971 std::enable_if_t<has_fast_inequality_check_v<Derived, Other>>> = nullptr>
972 ARENE_NODISCARD friend constexpr auto operator==(Self const& lhs, Other const& rhs) noexcept -> bool {
973 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
974 // side-effects"
975 static_assert(noexcept(Derived::three_way_compare(lhs, rhs)), "three_way_compare must be noexcept");
976 static_assert(noexcept(Derived::fast_inequality_check(lhs, rhs)), "fast_inequality_check must be noexcept");
977 // parasoft-end-suppress CERT_C-PRE31-c-3
978 return (Derived::fast_inequality_check(lhs, rhs) == inequality_heuristic::may_be_equal_or_not_equal) &&
979 (Derived::three_way_compare(lhs, rhs) == strong_ordering::equal);
980 }
981 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
982
983 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
984 /// @brief Equality comparison operator for instances of @c Derived with @c Other.
985 /// @tparam Self the type of the @c Derived object to compare, used for constraints
986 /// @tparam Other the type of the object to compare to
987 /// @param lhs The instance of @c Derived to compare
988 /// @param rhs The instance of @c Other to compare
989 /// @return bool @c true if @c lhs is equal to @c rhs, @c false otherwise
990 /// @pre @c Derived::three_way_compare(rhs,lhs) is well-formed
991 /// @pre @c Other::three_way_compare(lhs,rhs) is *not* well-formed
992 template <
993 typename Self,
994 typename Other,
995 constraints<
996 std::enable_if_t<std::is_same<Self, Derived>::value>,
997 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>,
998 std::enable_if_t<!is_three_way_comparable_v<Other, Derived>>> = nullptr>
999 ARENE_NODISCARD friend constexpr auto operator==(Other const& lhs, Self const& rhs) noexcept -> bool {
1000 return rhs == lhs;
1001 }
1002 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
1003
1004 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
1005 /// @brief Inequality comparison operator for instances of @c Derived with @c Other.
1006 /// @tparam Self the type of the @c Derived object to compare, used for constraints
1007 /// @tparam Other the type of the object to compare to
1008 /// @param lhs The instance of @c Derived to compare
1009 /// @param rhs The instance of @c Other to compare
1010 /// @return bool @c true if @c lhs is not equal to @c rhs, @c false otherwise
1011 /// @pre @c Derived::three_way_compare(lhs,rhs) is well-formed
1012 template <
1013 typename Self,
1014 typename Other,
1015 constraints<
1016 std::enable_if_t<std::is_same<Self, Derived>::value>,
1017 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>> = nullptr>
1018 ARENE_NODISCARD friend constexpr auto operator!=(Self const& lhs, Other const& rhs) noexcept -> bool {
1019 return !(lhs == rhs);
1020 }
1021 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
1022
1023 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
1024 /// @brief Inequality comparison operator for instances of @c Derived with @c Other.
1025 /// @tparam Self the type of the @c Derived object to compare, used for constraints
1026 /// @tparam Other the type of the object to compare to
1027 /// @param lhs The instance of @c Derived to compare
1028 /// @param rhs The instance of @c Other to compare
1029 /// @return bool @c true if @c lhs is not equal to @c rhs, @c false otherwise
1030 /// @pre @c Derived::three_way_compare(rhs,lhs) is well-formed
1031 /// @pre @c Other::three_way_compare(lhs,rhs) is *not* well-formed
1032 template <
1033 typename Self,
1034 typename Other,
1035 constraints<
1036 std::enable_if_t<std::is_same<Self, Derived>::value>,
1037 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>,
1038 std::enable_if_t<!is_three_way_comparable_v<Other, Derived>>> = nullptr>
1039 ARENE_NODISCARD friend constexpr auto operator!=(Other const& lhs, Self const& rhs) noexcept -> bool {
1040 return !(lhs == rhs);
1041 }
1042 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
1043
1044 protected:
1045 /// @brief Default constructor is protected
1046 constexpr generic_ordering_from_three_way_compare() noexcept = default;
1047 /// @brief Default destructor is protected
1048 ~generic_ordering_from_three_way_compare() noexcept = default;
1049 /// @brief Default copy constructor is protected
1050 /// @param other The source object
1051 constexpr generic_ordering_from_three_way_compare(generic_ordering_from_three_way_compare const& other
1052 ) noexcept = default;
1053 /// @brief Default move constructor is protected
1054 /// @param other The source object
1055 constexpr generic_ordering_from_three_way_compare(generic_ordering_from_three_way_compare&& other) noexcept = default;
1056 /// @brief Default copy assignment is protected
1057 /// @param other The source object
1058 constexpr auto operator=(generic_ordering_from_three_way_compare const& other) & noexcept
1059 -> generic_ordering_from_three_way_compare& = default;
1060 /// @brief Default move assignment is protected
1061 /// @param other The source object
1062 constexpr auto operator=(generic_ordering_from_three_way_compare&& other) & noexcept
1063 -> generic_ordering_from_three_way_compare& = default;
1064};
1065
1066namespace operators_detail {
1067/// @brief Type trait to check if we can provide a reversed operator== for this pair of types (breaks an infinite loop)
1068/// @tparam Self The type which is inheriting from this operator mixin
1069/// @tparam Other The type which we're trying to compare with (the LHS of a *reversed* comparison)
1070template <typename Self, typename Other>
1071constexpr bool eligible_for_reversed_equals_with_v =
1072 !std::is_same<Self, Other>::value && is_equality_comparable_v<Self, Other>;
1073} // namespace operators_detail
1074
1075/// @brief Helper class that can be inherited from by a class to define the relational comparison operators in terms of
1076/// a @c three_way_compare function provided by the @c Derived class, but preferentially implementing @c == and @c !=
1077/// to use <c>operator==(Derived, Other)</c> rather than <c>three_way_compare</c>.
1078///
1079/// Generates the @c <, @c >, @c <=, and @c >= comparison operators from a possibly overloaded @c static member function
1080/// @c three_way_compare in the @c Derived class that accepts a <c>const Derived&</c> as the first argument and any
1081/// other type as the second argument, and returns a @c strong_ordering value indicating whether the first is less than,
1082/// equal to or greater than the second. These @c three_way_compare functions must not throw exceptions.
1083///
1084/// Even if the derived class provides a @c fast_inequality_check function, it is not used, because the exact @c
1085/// operator== is preferred over <c>three_way_compare</c>.
1086///
1087/// @tparam Derived The type of the derived class. The comparison operators provided take parameters of this type.
1088///
1089/// For example:
1090/// @snippet docs/examples/ordering_examples.cpp three_way_and_equals_mixin_example
1091///
1092/// Here, @c MyClass has comparison operators for comparing instances of @c MyClass with each other, or with @c
1093/// OtherClass, or with @c YetAnotherClass. Equality comparisons with @c OtherClass will use <c>operator==</c>, while
1094/// comparisons with @c YetAnotherClass will use <c>three_way_compare</c>.
1095template <typename Derived>
1096class generic_ordering_from_three_way_compare_and_equals {
1097 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
1098 /// @brief Less-than comparison operator for instances of @c Derived with @c Other.
1099 /// @tparam Self the type of the @c Derived object to compare, used for constraints
1100 /// @tparam Other the type of the object to compare to
1101 /// @param lhs The instance of @c Derived to compare
1102 /// @param rhs The instance of @c Other to compare
1103 /// @return bool @c true if @c lhs is less than @c rhs, @c false otherwise
1104 template <
1105 typename Self,
1106 typename Other,
1107 constraints<
1108 std::enable_if_t<std::is_same<Self, Derived>::value>,
1109 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>> = nullptr>
1110 ARENE_NODISCARD friend constexpr auto operator<(Self const& lhs, Other const& rhs) noexcept -> bool {
1111 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
1112 // side-effects"
1113 static_assert(noexcept(Derived::three_way_compare(lhs, rhs)), "three_way_compare must be noexcept");
1114 // parasoft-end-suppress CERT_C-PRE31-c-3
1115 return Derived::three_way_compare(lhs, rhs) == strong_ordering::less;
1116 }
1117 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
1118
1119 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
1120 /// @brief Less-than comparison operator for instances of @c Derived with @c Other.
1121 /// @tparam Self the type of the @c Derived object to compare, used for constraints
1122 /// @tparam Other The type of the object to compare to
1123 /// @param lhs The instance of @c Other to compare
1124 /// @param rhs The instance of @c Derived to compare
1125 /// @return bool @c true if @c lhs is less than @c rhs, @c false otherwise
1126 template <
1127 typename Self,
1128 typename Other,
1129 constraints<
1130 std::enable_if_t<std::is_same<Self, Derived>::value>,
1131 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>,
1132 std::enable_if_t<!is_three_way_comparable_v<Other, Derived>>> = nullptr>
1133 ARENE_NODISCARD friend constexpr auto operator<(Other const& lhs, Self const& rhs) noexcept -> bool {
1134 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
1135 // side-effects"
1136 static_assert(noexcept(Derived::three_way_compare(rhs, lhs)), "three_way_compare must be noexcept");
1137 // parasoft-end-suppress CERT_C-PRE31-c-3
1138 return Derived::three_way_compare(rhs, lhs) == strong_ordering::greater;
1139 }
1140 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
1141
1142 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
1143 /// @brief Greater-than comparison operator for instances of @c Derived with @c Other.
1144 /// @tparam Self the type of the @c Derived object to compare, used for constraints
1145 /// @tparam Other the type of the object to compare to
1146 /// @param lhs The instance of @c Derived to compare
1147 /// @param rhs The instance of @c Other to compare
1148 /// @return bool @c true if @c lhs is greater than @c rhs, @c false otherwise
1149 template <
1150 typename Self,
1151 typename Other,
1152 constraints<
1153 std::enable_if_t<std::is_same<Self, Derived>::value>,
1154 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>> = nullptr>
1155 ARENE_NODISCARD friend constexpr auto operator>(Self const& lhs, Other const& rhs) noexcept -> bool {
1156 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
1157 // side-effects"
1158 static_assert(noexcept(Derived::three_way_compare(lhs, rhs)), "three_way_compare must be noexcept");
1159 // parasoft-end-suppress CERT_C-PRE31-c-3
1160 return Derived::three_way_compare(lhs, rhs) == strong_ordering::greater;
1161 }
1162 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
1163
1164 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
1165 /// @brief Greater-than comparison operator for instances of @c Derived with @c Other.
1166 /// @tparam Self the type of the @c Derived object to compare, used for constraints
1167 /// @tparam Other the type of the object to compare to
1168 /// @param lhs The instance of @c Other to compare
1169 /// @param rhs The instance of @c Derived to compare
1170 /// @return bool @c true if @c lhs is greater than @c rhs, @c false otherwise
1171 template <
1172 typename Self,
1173 typename Other,
1174 constraints<
1175 std::enable_if_t<std::is_same<Self, Derived>::value>,
1176 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>,
1177 std::enable_if_t<!is_three_way_comparable_v<Other, Derived>>> = nullptr>
1178 ARENE_NODISCARD friend constexpr auto operator>(Other const& lhs, Self const& rhs) noexcept -> bool {
1179 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
1180 // side-effects"
1181 static_assert(noexcept(Derived::three_way_compare(rhs, lhs)), "three_way_compare must be noexcept");
1182 // parasoft-end-suppress CERT_C-PRE31-c-3
1183 return Derived::three_way_compare(rhs, lhs) == strong_ordering::less;
1184 }
1185 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
1186
1187 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
1188 /// @brief Less-than-or-equal comparison operator for instances of @c Derived with @c Other.
1189 /// @tparam Self the type of the @c Derived object to compare, used for constraints
1190 /// @tparam Other the type of the object to compare to
1191 /// @param lhs The instance of @c Derived to compare
1192 /// @param rhs The instance of @c Other to compare
1193 /// @return bool @c true if @c lhs is less than or equal to @c rhs, @c false otherwise
1194 template <
1195 typename Self,
1196 typename Other,
1197 constraints<
1198 std::enable_if_t<std::is_same<Self, Derived>::value>,
1199 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>> = nullptr>
1200 ARENE_NODISCARD friend constexpr auto operator<=(Self const& lhs, Other const& rhs) noexcept -> bool {
1201 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
1202 // side-effects"
1203 static_assert(noexcept(Derived::three_way_compare(lhs, rhs)), "three_way_compare must be noexcept");
1204 // parasoft-end-suppress CERT_C-PRE31-c-3
1205 return Derived::three_way_compare(lhs, rhs) != strong_ordering::greater;
1206 }
1207 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
1208
1209 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
1210 /// @brief Less-than-or-equal comparison operator for instances of @c Derived with @c Other.
1211 /// @tparam Self the type of the @c Derived object to compare, used for constraints
1212 /// @tparam Other the type of the object to compare to
1213 /// @param lhs The instance of @c Other to compare
1214 /// @param rhs The instance of @c Derived to compare
1215 /// @return bool @c true if @c lhs is less than or equal to @c rhs, @c false otherwise
1216 template <
1217 typename Self,
1218 typename Other,
1219 constraints<
1220 std::enable_if_t<std::is_same<Self, Derived>::value>,
1221 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>,
1222 std::enable_if_t<!is_three_way_comparable_v<Other, Derived>>> = nullptr>
1223 ARENE_NODISCARD friend constexpr auto operator<=(Other const& lhs, Self const& rhs) noexcept -> bool {
1224 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
1225 // side-effects"
1226 static_assert(noexcept(Derived::three_way_compare(rhs, lhs)), "three_way_compare must be noexcept");
1227 // parasoft-end-suppress CERT_C-PRE31-c-3
1228 return Derived::three_way_compare(rhs, lhs) != strong_ordering::less;
1229 }
1230 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
1231
1232 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
1233 /// @brief Greater-than-or-equal comparison operator for instances of @c Derived with @c Other.
1234 /// @tparam Self the type of the @c Derived object to compare, used for constraints
1235 /// @tparam Other the type of the object to compare to
1236 /// @param lhs The instance of @c Derived to compare
1237 /// @param rhs The instance of @c Other to compare
1238 /// @return bool @c true if @c lhs is greater than or equal to @c rhs, @c false otherwise
1239 template <
1240 typename Self,
1241 typename Other,
1242 constraints<
1243 std::enable_if_t<std::is_same<Self, Derived>::value>,
1244 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>> = nullptr>
1245 ARENE_NODISCARD friend constexpr auto operator>=(Self const& lhs, Other const& rhs) noexcept -> bool {
1246 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
1247 // side-effects"
1248 static_assert(noexcept(Derived::three_way_compare(lhs, rhs)), "three_way_compare must be noexcept");
1249 // parasoft-end-suppress CERT_C-PRE31-c-3
1250 return Derived::three_way_compare(lhs, rhs) != strong_ordering::less;
1251 }
1252 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
1253
1254 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
1255 /// @brief Greater-than-or-equal comparison operator for instances of @c Derived with @c Other.
1256 /// @tparam Self the type of the @c Derived object to compare, used for constraints
1257 /// @tparam Other the type of the object to compare to
1258 /// @param lhs The instance of @c Other to compare
1259 /// @param rhs The instance of @c Derived to compare
1260 /// @return bool @c true if @c lhs is greater than or equal to @c rhs, @c false otherwise
1261 template <
1262 typename Self,
1263 typename Other,
1264 constraints<
1265 std::enable_if_t<std::is_same<Self, Derived>::value>,
1266 std::enable_if_t<is_three_way_comparable_v<Derived, Other>>,
1267 std::enable_if_t<!is_three_way_comparable_v<Other, Derived>>> = nullptr>
1268 ARENE_NODISCARD friend constexpr auto operator>=(Other const& lhs, Self const& rhs) noexcept -> bool {
1269 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
1270 // side-effects"
1271 static_assert(noexcept(Derived::three_way_compare(rhs, lhs)), "three_way_compare must be noexcept");
1272 // parasoft-end-suppress CERT_C-PRE31-c-3
1273 return Derived::three_way_compare(rhs, lhs) != strong_ordering::greater;
1274 }
1275 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
1276
1277 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
1278 /// @brief Equality comparison operator for instances of @c Derived with @c Other.
1279 /// @tparam Self the type of the @c Derived object to compare, used for constraints
1280 /// @tparam Other the type of the object to compare to
1281 /// @param lhs The instance of @c Derived to compare
1282 /// @param rhs The instance of @c Other to compare
1283 /// @return bool @c true if @c lhs is equal to @c rhs, @c false otherwise
1284 template <
1285 typename Self,
1286 typename Other,
1287 constraints<
1288 std::enable_if_t<std::is_same<Self, Derived>::value>,
1289 std::enable_if_t<operators_detail::eligible_for_reversed_equals_with_v<Self, Other>>> = nullptr>
1290 ARENE_NODISCARD friend constexpr auto operator==(Other const& lhs, Self const& rhs) noexcept -> bool {
1291 return rhs == lhs;
1292 }
1293 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
1294
1295 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
1296 /// @brief Inequality comparison operator for instances of @c Derived with @c Other.
1297 /// @tparam Self the type of the @c Derived object to compare, used for constraints
1298 /// @tparam Other the type of the object to compare to
1299 /// @param lhs The instance of @c Derived to compare
1300 /// @param rhs The instance of @c Other to compare
1301 /// @return bool @c true if @c lhs is not equal to @c rhs, @c false otherwise
1302 template <
1303 typename Self,
1304 typename Other,
1305 constraints<
1306 std::enable_if_t<std::is_same<Self, Derived>::value>,
1307 std::enable_if_t<is_equality_comparable_v<Self, Other>>> = nullptr>
1308 ARENE_NODISCARD friend constexpr auto operator!=(Self const& lhs, Other const& rhs) noexcept -> bool {
1309 return !(lhs == rhs);
1310 }
1311 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
1312
1313 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
1314 /// @brief Inequality comparison operator for instances of @c Derived with @c Other.
1315 /// @tparam Self the type of the @c Derived object to compare, used for constraints
1316 /// @tparam Other the type of the object to compare to
1317 /// @param lhs The instance of @c Derived to compare
1318 /// @param rhs The instance of @c Other to compare
1319 /// @return bool @c true if @c lhs is not equal to @c rhs, @c false otherwise
1320 template <
1321 typename Self,
1322 typename Other,
1323 constraints<
1324 std::enable_if_t<std::is_same<Self, Derived>::value>,
1325 std::enable_if_t<operators_detail::eligible_for_reversed_equals_with_v<Self, Other>>> = nullptr>
1326 ARENE_NODISCARD friend constexpr auto operator!=(Other const& lhs, Self const& rhs) noexcept -> bool {
1327 return !(lhs == rhs);
1328 }
1329
1330 protected:
1331 /// @brief Default constructor is protected
1332 constexpr generic_ordering_from_three_way_compare_and_equals() noexcept = default;
1333 /// @brief Default destructor is protected
1334 ~generic_ordering_from_three_way_compare_and_equals() noexcept = default;
1335 /// @brief Default copy constructor is protected
1336 /// @param other The source object
1337 constexpr generic_ordering_from_three_way_compare_and_equals(
1338 generic_ordering_from_three_way_compare_and_equals const& other
1339 ) noexcept = default;
1340 /// @brief Default move constructor is protected
1341 /// @param other The source object
1342 constexpr generic_ordering_from_three_way_compare_and_equals(
1343 generic_ordering_from_three_way_compare_and_equals&& other
1344 ) noexcept = default;
1345 /// @brief Default copy assignment is protected
1346 /// @param other The source object
1347 constexpr auto operator=(generic_ordering_from_three_way_compare_and_equals const& other) & noexcept
1348 -> generic_ordering_from_three_way_compare_and_equals& = default;
1349 /// @brief Default move assignment is protected
1350 /// @param other The source object
1351 constexpr auto operator=(generic_ordering_from_three_way_compare_and_equals&& other) & noexcept
1352 -> generic_ordering_from_three_way_compare_and_equals& = default;
1353};
1354
1355} // namespace base
1356} // namespace arene
1357
1358// parasoft-end-suppress AUTOSAR-A11_3_1-a-2
1359// parasoft-end-suppress AUTOSAR-A13_5_5-b-2
1360
1361#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_COMPARE_OPERATORS_HPP_
Definition array_exceptions_disabled.cpp:11
ARENE_IGNORE_ALL("-Wfloat-equal", "Equality is used to check the properties of a single value, not compare two values")
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10