Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
strong_ordering.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_STRONG_ORDERING_HPP_
6#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_COMPARE_STRONG_ORDERING_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 pmeritted 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/contracts/contract.hpp"
15#include "arene/base/stdlib_choice/cstdint.hpp"
16#include "arene/base/stdlib_choice/integral_constant.hpp"
17#include "arene/base/type_traits/is_invocable.hpp"
18#include "arene/base/type_traits/is_transparent_comparator_for.hpp"
19// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
20
21// parasoft-begin-suppress AUTOSAR-A13_5_5-b-2 "Mixed comparisons permitted by A13-5-5 Permit #1"
22
23namespace arene {
24namespace base {
25
26namespace strong_ordering_detail {
27/// @brief Internal helper class for providing a type that is constructible from literal @c 0, but not from a general
28/// integer
29class comparison_marker_helper {
30 /// @brief Private type inaccessible from elsewhere
31 class internal {};
32
33 public:
34 /// @brief A class member pointer pointing to a data member of a private type, for which there are no instances.
35 /// Constructible from @c 0 or @c nullptr but not from a general integer or pointer.
36 using comp_ptr = comparison_marker_helper::internal comparison_marker_helper::*;
37};
38
39/// @brief A special type for use as an argument for @c strong_ordering comparison operators to allow comparisons
40/// between @c strong_ordering values and literal @c 0, without allowing too many implicit conversions.
41using comparison_marker_type = comparison_marker_helper::comp_ptr;
42
43/// @brief The result type of a three-way comparison. Equivalent to @c std::strong_ordering from C++20.
44enum class strong_ordering : std::int8_t {
45 /// @brief Return value to indicate that the lhs of the comparison was less than the rhs.
46 less = -1,
47 /// @brief Return value to indicate that the lhs of the comparison was equal to the rhs.
48 equal = 0,
49 /// @brief Return value to indicate that the lhs of the comparison was greater than the rhs.
50 greater = 1
51};
52
53/// @brief Comparison for @c strong_ordering against literal 0
54/// @param lhs the value being checked
55/// @return bool @c true if @c lhs is @c strong_ordering::equal, @c false otherwise.
56inline constexpr auto operator==(strong_ordering const lhs, comparison_marker_type) noexcept -> bool {
57 return lhs == strong_ordering::equal;
58}
59
60/// @brief Comparison for @c strong_ordering against literal 0
61/// @param rhs the value being checked
62/// @return bool @c true if @c rhs is @c strong_ordering::equal, @c false otherwise.
63inline constexpr auto operator==(comparison_marker_type, strong_ordering const rhs) noexcept -> bool {
64 return strong_ordering::equal == rhs;
65}
66
67/// @brief Comparison for @c strong_ordering against literal 0
68/// @param lhs the value being checked
69/// @return bool @c true if @c lhs is not @c strong_ordering::equal, @c false otherwise.
70inline constexpr auto operator!=(strong_ordering const lhs, comparison_marker_type) noexcept -> bool {
71 return lhs != strong_ordering::equal;
72}
73
74/// @brief Comparison for @c strong_ordering against literal 0
75/// @param rhs the value being checked
76/// @return bool @c true if @c rhs is not @c strong_ordering::equal, @c false otherwise.
77inline constexpr auto operator!=(comparison_marker_type, strong_ordering const rhs) noexcept -> bool {
78 return strong_ordering::equal != rhs;
79}
80
81/// @brief Comparison for @c strong_ordering against literal 0
82/// @param lhs the value being checked
83/// @return bool @c true if @c lhs is @c strong_ordering::less, @c false otherwise.
84inline constexpr auto operator<(strong_ordering const lhs, comparison_marker_type) noexcept -> bool {
85 // parasoft-begin-suppress AUTOSAR-M0_1_2-e-2 "False positive: lhs could be anything"
86 return lhs < strong_ordering::equal;
87 // parasoft-end-suppress AUTOSAR-M0_1_2-e-2
88}
89
90/// @brief Comparison for @c strong_ordering against literal 0
91/// @param rhs the value being checked
92/// @return bool @c true if @c rhs is @c strong_ordering::greater, @c false otherwise.
93inline constexpr auto operator<(comparison_marker_type, strong_ordering const rhs) noexcept -> bool {
94 return strong_ordering::equal < rhs;
95}
96
97/// @brief Comparison for @c strong_ordering against literal 0
98/// @param lhs the value being checked
99/// @return bool @c true if @c lhs is @c strong_ordering::equal or @c strong_ordering::less, @c false otherwise.
100inline constexpr auto operator<=(strong_ordering const lhs, comparison_marker_type) noexcept -> bool {
101 return lhs <= strong_ordering::equal;
102}
103
104/// @brief Comparison for @c strong_ordering against literal 0
105/// @param rhs the value being checked
106/// @return bool @c true if @c rhs is @c strong_ordering::equal or @c strong_ordering::greater, @c false otherwise.
107inline constexpr auto operator<=(comparison_marker_type, strong_ordering const rhs) noexcept -> bool {
108 // parasoft-begin-suppress AUTOSAR-M0_1_2-b-2 "False positive: rhs could be anything"
109 return strong_ordering::equal <= rhs;
110 // parasoft-end-suppress AUTOSAR-M0_1_2-b-2
111}
112
113/// @brief Comparison for @c strong_ordering against literal 0
114/// @param lhs the value being checked
115/// @return bool @c true if @c lhs is @c strong_ordering::greater, @c false otherwise.
116inline constexpr auto operator>(strong_ordering const lhs, comparison_marker_type) noexcept -> bool {
117 return lhs > strong_ordering::equal;
118}
119
120/// @brief Comparison for @c strong_ordering against literal 0
121/// @param rhs the value being checked
122/// @return bool @c true if @c lhs is @c strong_ordering::greater, @c false otherwise.
123inline constexpr auto operator>(comparison_marker_type, strong_ordering const rhs) noexcept -> bool {
124 // parasoft-begin-suppress AUTOSAR-M0_1_2-b-2 "False positive: rhs could be anything"
125 return strong_ordering::equal > rhs;
126 // parasoft-end-suppress AUTOSAR-M0_1_2-b-2
127}
128
129/// @brief Comparison for @c strong_ordering against literal 0
130/// @param lhs the value being checked
131/// @return bool @c true if @c lhs is @c strong_ordering::equal or @c strong_ordering::greater, @c false otherwise.
132inline constexpr auto operator>=(strong_ordering const lhs, comparison_marker_type) noexcept -> bool {
133 // parasoft-begin-suppress AUTOSAR-M0_1_2-e-2 "False positive: lhs could be anything"
134 return lhs >= strong_ordering::equal;
135 // parasoft-end-suppress AUTOSAR-M0_1_2-e-2
136}
137
138/// @brief Comparison for @c strong_ordering against literal 0
139/// @param rhs the value being checked
140/// @return bool @c true if @c rhs is @c strong_ordering::equal or @c strong_ordering::less, @c false otherwise.
141inline constexpr auto operator>=(comparison_marker_type, strong_ordering const rhs) noexcept -> bool {
142 return strong_ordering::equal >= rhs;
143}
144} // namespace strong_ordering_detail
145
146/// @brief The enumeration specifying the result of an ordering comparison
147using strong_ordering = strong_ordering_detail::strong_ordering;
148
149// parasoft-begin-suppress AUTOSAR-A3_9_1-b-2 "Conversion of strong_ordering to and from 'int' is deliberate choice, for
150// compatibility with existing APIs that produce or expect an 'int' result"
151
152/// @brief Convert an integer three-way-comparison result into a @c strong_ordering.
153/// @param three_way_result The result to convert.
154/// @return strong_ordering @c strong_ordering::less if @c three_way_result is less than zero, @c strong_ordering::equal
155/// if @c three_way_result is equal to zero, and @c strong_ordering::greater if @c three_way_result is greater than
156/// zero.
157inline constexpr auto make_strong_ordering(int const three_way_result) noexcept -> strong_ordering {
158 if (three_way_result < 0) {
159 return strong_ordering::less;
160 }
161 if (three_way_result == 0) {
162 return strong_ordering::equal;
163 }
164 return strong_ordering::greater;
165}
166
167// parasoft-begin-suppress AUTOSAR-A8_4_2-a-2 "ARENE_UNREACHABLE terminates if it is ever reached, so does not need a
168// return"
169// parasoft-begin-suppress CERT_C-MSC37-a-2 "ARENE_UNREACHABLE terminates if it is ever reached, so does not need a
170// return"
171// parasoft-begin-suppress CERT_CPP-MSC52-a-2 "ARENE_UNREACHABLE terminates if it is ever reached, so does not need a
172// return"
173/// @brief Convert a @c strong_ordering into an integer three-way-comparison result.
174/// @param ordering The ordering to convert.
175/// @return int @c -1 if @c ordering is strong_ordering::less, @c 0 if @c ordering is strong_ordering::equal, and @c 1
176/// if @c ordering is strong_ordering::greater.
177inline constexpr auto from_strong_ordering(strong_ordering const ordering) noexcept -> int {
178 // parasoft-begin-suppress AUTOSAR-M6_4_5-a-2 "All branches terminated with return as per permit M6-4-5#1"
179 // parasoft-begin-suppress AUTOSAR-M6_4_3-a-2 "All branches terminated with return as per permit M6-4-3#1"
180 switch (ordering) {
181 case strong_ordering::less:
182 return -1;
183 case strong_ordering::equal:
184 return 0;
185 case strong_ordering::greater:
186 return 1;
187 }
188 // parasoft-end-suppress AUTOSAR-M6_4_5-a-2
189 // parasoft-end-suppress AUTOSAR-M6_4_3-a-2
190 ARENE_INVARIANT_UNREACHABLE("Invalid ordering");
191}
192// parasoft-end-suppress CERT_CPP-MSC52-a-2
193// parasoft-end-suppress CERT_C-MSC37-a-2
194// parasoft-end-suppress AUTOSAR-A8-4-2-a-2
195// parasoft-end-suppress AUTOSAR-A3_9_1-b-2
196
197// parasoft-begin-suppress AUTOSAR-A8_4_2-a-2 "ARENE_UNREACHABLE to terminate if it is ever reached, so does not need a
198// return"
199// parasoft-begin-suppress CERT_C-MSC37-a-2 "ARENE_UNREACHABLE terminates if it is ever reached, so does not need a
200// return"
201// parasoft-begin-suppress CERT_CPP-MSC52-a-2 "ARENE_UNREACHABLE terminates if it is ever reached, so does not need a
202// return"
203/// @brief Return the opposite ordering for a @c strong_ordering three-way-comparison
204/// result.
205/// @param ordering The ordering to convert.
206/// @return strong_ordering @c strong_ordering::greater if @c ordering is strong_ordering::less, @c
207/// strong_ordering::equal if @c ordering is strong_ordering::equal, and @c strong_ordering::less if @c ordering is
208/// strong_ordering::greater.
209inline constexpr auto opposite_ordering(strong_ordering const ordering) noexcept -> strong_ordering {
210 // parasoft-begin-suppress AUTOSAR-M6_4_5-a-2 "All branches terminated with return as per permit M6-4-5#1"
211 // parasoft-begin-suppress AUTOSAR-M6_4_3-a-2 "All branches terminated with return as per permit M6-4-3#1"
212 switch (ordering) {
213 case strong_ordering::less:
214 return strong_ordering::greater;
215 case strong_ordering::greater:
216 return strong_ordering::less;
217 case strong_ordering::equal:
218 return strong_ordering::equal;
219 }
220 // parasoft-end-suppress AUTOSAR-M6_4_5-a-2
221 // parasoft-end-suppress AUTOSAR-M6_4_3-a-2
222 ARENE_INVARIANT_UNREACHABLE("Invalid ordering");
223}
224// parasoft-end-suppress CERT_CPP-MSC52-a-2
225// parasoft-end-suppress CERT_C-MSC37-a-2
226// parasoft-end-suppress AUTOSAR-A8-4-2-a-2
227
228/// @brief Trait to determine if a given type is a _transparent comparator_ that performs a three-way comparison for a
229/// given set of operands.
230///
231/// @tparam C The type to test
232/// @tparam T The type of the left hand operand
233/// @tparam U The type of the right hand operand
234/// @return bool Will be equivalent to <c>is_transparent_comparator_v<C> && is_invocable_r_v<strong_ordering, C, T,
235/// U></c>.
236
237template <typename C, typename T, typename U = T>
238extern constexpr bool is_transparent_three_way_comparator_for_v =
240
241/// @brief Trait to determine if a given type is a _transparent comparator_ for a given set of operands.
242///
243/// @tparam C The type to test
244/// @tparam T The type of the left hand operand
245/// @tparam U The type of the right hand operand
246/// Value will be equivalent to <c>is_transparent_three_way_comparator_v<C> && is_invocable_r_v<strong_ordering, C,
247/// T, U></c>.
248template <typename C, typename T, typename U = T>
251
252} // namespace base
253} // namespace arene
254
255// parasoft-end-suppress AUTOSAR-A13_5_5-b-2
256
257#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_COMPARE_STRONG_ORDERING_HPP_
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10