Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
lexicographical_compare.hpp
Go to the documentation of this file.
1// Copyright 2026, Toyota Motor Corporation
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5///
6/// @file lexicographical_compare.hpp
7/// @brief Provides an implementation of a backport of @c std::lexicographical_compare from C++20
8///
9#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_LEXICOGRAPHICAL_COMPARE_HPP_
10#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_LEXICOGRAPHICAL_COMPARE_HPP_
11
12// IWYU pragma: private, include "arene/base/algorithm.hpp"
13// IWYU pragma: friend "(arene/base(?!/tests)|stdlib/include/stdlib_detail)/.*"
14
15// parasoft-begin-suppress AUTOSAR-A16_2_2-a-2 "Arene Base aggregate headers permitted by A16-2-2 Permit #1"
16#include "arene/base/compare/compare_three_way.hpp"
17#include "arene/base/compare/strong_ordering.hpp"
18#include "arene/base/compiler_support/attributes.hpp"
19#include "arene/base/compiler_support/cpp14_inline.hpp"
20#include "arene/base/iterator/advance.hpp"
21#include "arene/base/stdlib_choice/less.hpp"
22#include "arene/base/type_traits/is_invocable.hpp"
23// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
24
25namespace arene {
26namespace base {
27
28namespace lexicographical_compare_detail {
29
30/// @brief Implementation class for performing lexicographical comparison across two iterator ranges based on a binary
31/// predicate
32class lexicographical_compare_fn {
33 public:
34 /// @brief Performa lexicographical comparison across two iterator ranges based on a binary predicate
35 /// @tparam Itr1 The iterator type for the first range
36 /// @tparam Itr2 The iterator type for the second range
37 /// @tparam BinaryPredicate The type of the predicate
38 /// @param first_itr The start of the first range
39 /// @param first_end The end of the first range
40 /// @param second_itr The start of the second range
41 /// @param second_end The end of the second range
42 /// @param cmp The predicate to use for comparison
43 /// @return bool @c true if the first range is lexicographically before the second, given the predicate, @c false
44 /// otherwise
45 template <typename Itr1, typename Itr2, typename BinaryPredicate = std::less<>>
46 ARENE_NODISCARD constexpr auto
47 operator()(Itr1 first_itr, Itr1 first_end, Itr2 second_itr, Itr2 second_end, BinaryPredicate cmp = {}) const noexcept
48 -> bool {
49 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
50 // side-effects"
51 static_assert(
52 is_invocable_r_v<bool, BinaryPredicate, decltype(*first_itr), decltype(*second_itr)>,
53 "cmp must be invocable with the elements from the input sequences and return a boolean-convertible value"
54 );
55 static_assert(
56 is_invocable_r_v<bool, BinaryPredicate, decltype(*second_itr), decltype(*first_itr)>,
57 "cmp must be invocable with the elements from the input sequences and return a boolean-convertible value"
58 );
59 // parasoft-end-suppress CERT_C-PRE31-c-3
60 bool first_at_end{first_itr == first_end};
61 bool second_at_end{second_itr == second_end};
62 while ((!first_at_end) && (!second_at_end)) {
63 if (cmp(*first_itr, *second_itr)) {
64 return true;
65 }
66 if (cmp(*second_itr, *first_itr)) {
67 return false;
68 }
69 arene::base::advance(first_itr, 1);
70 arene::base::advance(second_itr, 1);
71 first_at_end = first_itr == first_end;
72 second_at_end = second_itr == second_end;
73 }
74 return first_at_end && (!second_at_end);
75 }
76};
77
78/// @brief Implementation class for performing lexicographical comparison across two iterator ranges based on a
79/// three-way comparison predicate
80class lexicographical_compare_three_way_fn {
81 public:
82 /// @brief Performa lexicographical comparison across two iterator ranges based on a binary predicate
83 /// @tparam Itr1 The iterator type for the first range
84 /// @tparam Itr2 The iterator type for the second range
85 /// @tparam Comparator The type of the comparison predicate
86 /// @param first_itr The start of the first range
87 /// @param first_end The end of the first range
88 /// @param second_itr The start of the second range
89 /// @param second_end The end of the second range
90 /// @param tw_comp The predicate to use for comparison
91 /// @return strong_ordering @c strong_ordering::less if the first range is lexicographically ordered before the
92 /// second, @c strong_ordering::equal if the two ranges are lexicographically equivalent, otherwise @c
93 /// strong_ordering::greater to indicate that the first range is lexicographically ordered after the second, according
94 /// to the supplied predicate
95 template <typename Itr1, typename Itr2, typename Comparator = compare_three_way>
96 ARENE_NODISCARD constexpr auto
97 operator()(Itr1 first_itr, Itr1 first_end, Itr2 second_itr, Itr2 second_end, Comparator tw_comp = {}) const noexcept
98 -> strong_ordering {
99 // parasoft-begin-suppress CERT_C-PRE31-c-3 "False positive: static_assert is a compile-time assert and can have no
100 // side-effects"
101 static_assert(
102 is_invocable_r_v<strong_ordering, Comparator, decltype(*first_itr), decltype(*second_itr)>,
103 "tw_comp must be invocable with the value_type of the intput iterators and return a strong_ordering"
104 );
105 // parasoft-end-suppress CERT_C-PRE31-c-3
106 bool first_at_end{first_itr == first_end};
107 bool second_at_end{second_itr == second_end};
108 while ((!first_at_end) && (!second_at_end)) {
109 auto const comp_r = tw_comp(*first_itr, *second_itr);
110 if (comp_r != strong_ordering::equal) {
111 return comp_r;
112 }
113 arene::base::advance(first_itr, 1);
114 arene::base::advance(second_itr, 1);
115 first_at_end = first_itr == first_end;
116 second_at_end = second_itr == second_end;
117 }
118 if (first_at_end && (!second_at_end)) {
119 return strong_ordering::less;
120 }
121 return first_at_end && second_at_end ? strong_ordering::equal : strong_ordering::greater;
122 }
123};
124
125} // namespace lexicographical_compare_detail
126
127/// @def arene::base::lexicographical_compare
128/// @copydoc arene::base::lexicographical_compare_detail::lexicographical_compare_fn::operator()
129// parasoft-begin-suppress AUTOSAR-M7_3_3-a "An unnamed namespace is used to create a per-TU reference to a global
130// object used in multiple TUs."
131// parasoft-begin-suppress CERT_CPP-DCL59-a "An unnamed namespace is used to create a per-TU reference to a global
132// object used in multiple TUs."
133ARENE_CPP14_INLINE_VARIABLE(lexicographical_compare_detail::lexicographical_compare_fn, lexicographical_compare);
134// parasoft-end-suppress AUTOSAR-M7_3_3-a
135// parasoft-end-suppress CERT_CPP-DCL59-a
136
137/// @def arene::base::lexicographical_compare_three_way
138/// @copydoc arene::base::lexicographical_compare_detail::lexicographical_compare_three_way_fn::operator()
139// parasoft-begin-suppress AUTOSAR-M7_3_3-a "An unnamed namespace is used to create a per-TU reference to a global
140// object used in multiple TUs."
141// parasoft-begin-suppress CERT_CPP-DCL59-a "An unnamed namespace is used to create a per-TU reference to a global
142// object used in multiple TUs."
143ARENE_CPP14_INLINE_VARIABLE(
144 lexicographical_compare_detail::lexicographical_compare_three_way_fn,
145 lexicographical_compare_three_way
146);
147// parasoft-end-suppress AUTOSAR-M7_3_3-a
148// parasoft-end-suppress CERT_CPP-DCL59-a
149
150} // namespace base
151} // namespace arene
152
153#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_LEXICOGRAPHICAL_COMPARE_HPP_
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10