Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
equal.hpp
Go to the documentation of this file.
1// parasoft-begin-suppress AUTOSAR-A2_8_1-a-2 "False positive: also defines arene::base::equal"
2
3// Copyright 2026, Toyota Motor Corporation
4//
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
7///
8/// @file equal.hpp
9/// @brief Provides implementation of a backport of C++20's version of std::equal
10///
11#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_EQUAL_HPP_
12#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_EQUAL_HPP_
13
14// IWYU pragma: private, include "arene/base/algorithm.hpp"
15// IWYU pragma: friend "(arene/base(?!/tests)|stdlib/include/stdlib_detail)/.*"
16
17// parasoft-begin-suppress AUTOSAR-A16_2_2-a-2 "Arene Base aggregate headers permitted by A16-2-2 Permit #1"
18#include "arene/base/compiler_support/attributes.hpp"
19#include "arene/base/compiler_support/cpp14_inline.hpp"
20#include "arene/base/iterator/distance.hpp"
21#include "arene/base/stdlib_choice/equal_to.hpp"
22#include "arene/base/stdlib_choice/iterator_tags.hpp"
23#include "arene/base/stdlib_choice/iterator_traits.hpp"
24#include "arene/base/stdlib_choice/move.hpp"
25// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
26
27namespace arene {
28namespace base {
29namespace equal_detail {
30
31// parasoft-begin-suppress AUTOSAR-M3_3_2-a "False positive: inline function used in multiple translation units"
32
33///
34/// @brief Implementation helper for @c arene::base::equal .
35/// @see arene::base::equal(first_start,first_end,second_start,cmp)
36///
37/// @tparam Itr1 The iterator type for the first range
38/// @tparam Itr2 The iterator type for the second range
39/// @tparam BinaryPredicate The predicate type to apply to check for equality
40/// @param first_itr Iterator to the start of the first sequence
41/// @param first_end Iterator to the end of the first sequence
42/// @param second_itr Iterator to the start of the second sequence
43/// @param cmp Functor to use to compare elements in the sequences. A return of @c true from this functor means
44/// elements are equivalent. Will be called exactly once on each set of elements in the two sequences, and
45/// at most @c distance(first_itr,first_end) times. If omitted then @c std::equal_to is used.
46/// @return bool @c true if all elements in the sequence @c [first_itr,first_end) compare equivalent to the elements in
47/// the sequence equivalent to @c [second_itr,second_itr+distance(first_start,first_end)) else @c false
48/// @pre The iterator equivalent to @c second_itr+distance(first_itr,first_end) must be a valid iterator in the
49/// sequence represented by @c second_itr , else behavior is undefined.
50template <typename Itr1, typename Itr2, typename BinaryPredicate>
51ARENE_NODISCARD constexpr auto do_equal(Itr1 first_itr, Itr1 first_end, Itr2 second_itr, BinaryPredicate cmp) -> bool {
52 while (first_itr != first_end) {
53 if (!cmp(*first_itr, *second_itr)) {
54 return false;
55 }
56 // parasoft-begin-suppress AUTOSAR-M5_0_15-a "These are iterator types, so incrementing is ok"
57 ++first_itr;
58 ++second_itr;
59 // parasoft-end-suppress AUTOSAR-M5_0_15-a
60 }
61 return true;
62}
63
64///
65/// @brief Implementation helper for @c arene::base::equal .
66/// @see arene::base::equal(first_start,first_end,second_start,second_end,cmp)
67///
68/// @tparam Itr1 The iterator type for the first range
69/// @tparam Itr2 The iterator type for the second range
70/// @tparam BinaryPredicate The predicate type to apply to check for equality
71/// @param first_itr Iterator to the start of the first sequence
72/// @param first_end Iterator to the end of the first sequence
73/// @param second_itr Iterator to the start of the second sequence
74/// @param second_end Iterator to the end of the second sequence
75/// @param cmp Functor to use to compare elements in the sequences. A return of @c true from this functor means
76/// elements are equivalent. Will be called exactly once on each set of elements in the two sequences, and
77/// at most @c min(distance(first_itr,first_end),distance(second_itr,second_end)) times. If omitted then @c
78/// std::equal_to is used.
79/// @return bool @c true if the ranges are the same length, and all elements in the sequence @c [first_itr,first_end)
80/// compare equivalent to the elements in the sequence equivalent to @c [second_itr,second_end) else @c false
81template <typename Itr1, typename Itr2, typename BinaryPredicate>
82ARENE_NODISCARD constexpr auto do_equal(
83 std::input_iterator_tag,
84 Itr1 first_itr,
85 Itr1 first_end,
86 std::input_iterator_tag,
87 Itr2 second_itr,
88 Itr2 second_end,
89 BinaryPredicate cmp
90) noexcept -> bool {
91 while (first_itr != first_end && second_itr != second_end) {
92 if (!cmp(*first_itr, *second_itr)) {
93 return false;
94 }
95 ++first_itr;
96 ++second_itr;
97 }
98 return first_itr == first_end && second_itr == second_end;
99}
100
101///
102/// @brief Implementation helper for @c arene::base::equal . It specializes for random-access-iterators, allowing them
103/// to short circuit if the sequences are of different size.
104/// @see arene::base::equal(first_start,first_end,second_start,second_end,cmp)
105///
106/// @tparam Itr1 The iterator type for the first range
107/// @tparam Itr2 The iterator type for the second range
108/// @tparam BinaryPredicate The predicate type to apply to check for equality
109/// @param first_itr Iterator to the start of the first sequence
110/// @param first_end Iterator to the end of the first sequence
111/// @param second_itr Iterator to the start of the second sequence
112/// @param second_end Iterator to the end of the second sequence
113/// @param cmp Functor to use to compare elements in the sequences. A return of @c true from this functor means
114/// elements are equivalent. Will be called exactly once on each set of elements in the two sequences, and
115/// at most @c min(distance(first_itr,first_end),distance(second_itr,second_end)) times. If omitted then @c
116/// std::equal_to is used.
117/// @return bool @c true if the ranges are the same length, and all elements in the sequence @c [first_itr,first_end)
118/// compare equivalent to the elements in the sequence equivalent to @c [second_itr,second_end) else @c false
119template <typename Itr1, typename Itr2, typename BinaryPredicate>
120ARENE_NODISCARD constexpr auto do_equal(
121 std::random_access_iterator_tag,
122 Itr1 first_itr,
123 Itr1 first_end,
124 std::random_access_iterator_tag,
125 Itr2 second_itr,
126 Itr2 second_end,
127 BinaryPredicate cmp
128) noexcept -> bool {
129 // We call the non-second-end consuming overload of do_equal here because we know the ranges are equal length and
130 // this saves an iterator comparison per increment plus two iterator comparisons at end for equal sequence.
131 return (::arene::base::distance(first_itr, first_end) == ::arene::base::distance(second_itr, second_end)) &&
132 do_equal(first_itr, first_end, second_itr, std::move(cmp));
133}
134
135// parasoft-end-suppress
136
137/// @brief A class for callable objects that implement equality checks for ranges
138class equal_fn {
139 public:
140 ///
141 /// @brief Compares a sequence with an equally sized sequence
142 ///
143 /// @tparam Itr1 Must model at least @c InputIterator
144 /// @tparam Itr2 Must model at least @c InputIterator
145 /// @param first_start Iterator to the start of the first sequence
146 /// @param first_end Iterator to the end of the first sequence
147 /// @param second_start Iterator to the start of the second sequence
148 /// @return bool @c true if all elements in the sequence @c [first_start,first_end) compare equivalent to the elements
149 /// in the sequence @c [second_start,second_start+distance(first_start,first_end)) else @c false
150 ///
151 /// @pre The iterator equivalent to @c second_start+distance(first_start,first_end) must be a valid iterator in the
152 /// sequence represented by @c second_start , else behavior is undefined.
153 template <typename Itr1, typename Itr2>
154 ARENE_NODISCARD constexpr auto operator()(Itr1 first_start, Itr1 first_end, Itr2 second_start) const noexcept
155 -> bool {
156 return (*this)(first_start, first_end, second_start, std::equal_to<>{});
157 }
158 ///
159 /// @brief Compares a sequence with an equally sized sequence using a given comparator.
160 ///
161 /// @tparam Itr1 Must model at least @c InputIterator
162 /// @tparam Itr2 Must model at least @c InputIterator
163 /// @tparam BinaryPredicate Must satisfy
164 /// <c>is_invocable_r_v<bool, BinaryPredicate, decltype(*first_start), decltype(*first_start)></c>
165 /// @param first_start Iterator to the start of the first sequence
166 /// @param first_end Iterator to the end of the first sequence
167 /// @param second_start Iterator to the start of the second sequence
168 /// @param cmp Functor to use to compare elements in the sequences. A return of @c true from this functor means
169 /// elements are equivalent. Will be called exactly once on each set of elements in the two sequences, and
170 /// at most @c distance(first_end,first_start) times.
171 /// @return bool @c true if all elements in the sequence @c [first_start,first_end) compare equivalent to the elements
172 /// in the sequence @c [second_start,second_start+distance(first_start,first_end)) else @c false
173 ///
174 /// @pre The iterator equivalent to @c second_start+distance(first_start,first_end) must be a valid iterator in the
175 /// sequence represented by @c second_start , else behavior is undefined.
176 template <typename Itr1, typename Itr2, typename BinaryPredicate>
177 ARENE_NODISCARD constexpr auto operator()(Itr1 first_start, Itr1 first_end, Itr2 second_start, BinaryPredicate cmp)
178 const noexcept -> bool {
179 return do_equal(first_start, first_end, second_start, std::move(cmp));
180 }
181
182 ///
183 /// @brief Compares a sequence with a potentially differently sized sequence
184 ///
185 /// @tparam Itr1 Must model at least @c InputIterator
186 /// @tparam Itr2 Must model at least @c InputIterator
187 /// @param first_start Iterator to the start of the first sequence
188 /// @param first_end Iterator to the end of the first sequence
189 /// @param second_start Iterator to the start of the second sequence
190 /// @param second_end Iterator to the end of the second sequence
191 /// @return bool @c true if the ranges are the same length, and all elements in the sequence @c [first_itr,first_end)
192 /// compare equivalent to the elements in the sequence equivalent to @c [second_itr,second_end) else @c
193 /// false
194 template <typename Itr1, typename Itr2>
195 ARENE_NODISCARD constexpr auto operator()(Itr1 first_start, Itr1 first_end, Itr2 second_start, Itr2 second_end)
196 const noexcept -> bool {
197 return (*this)(first_start, first_end, second_start, second_end, std::equal_to<>{});
198 }
199 ///
200 /// @brief Compares a sequence with a potentially differently sized sequence using a given comparator.
201 ///
202 /// @tparam Itr1 Must model at least @c InputIterator
203 /// @tparam Itr2 Must model at least @c InputIterator
204 /// @tparam BinaryPredicate Must satisfy
205 /// <c>is_invocable_r_v<bool, BinaryPredicate, decltype(*first_start), decltype(*first_start)></c>
206 /// @param first_start Iterator to the start of the first sequence
207 /// @param first_end Iterator to the end of the first sequence
208 /// @param second_start Iterator to the start of the second sequence
209 /// @param second_end Iterator to the end of the second sequence
210 /// @param cmp Functor to use to compare elements in the sequences. A return of @c true from this functor means
211 /// elements are equivalent. Will be called exactly once on each set of elements in the two sequences, and
212 /// at most @c std::min(distance(first_start,first_end),distance(second_first,second_end) times.
213 /// @return bool @c true if the ranges are the same length, and all elements in the sequence @c [first_itr,first_end)
214 /// compare equivalent to the elements in the sequence equivalent to @c [second_itr,second_end) else @c
215 /// false
216 template <typename Itr1, typename Itr2, typename BinaryPredicate>
217 ARENE_NODISCARD constexpr auto
218 operator()(Itr1 first_start, Itr1 first_end, Itr2 second_start, Itr2 second_end, BinaryPredicate cmp) const noexcept
219 -> bool {
220 return do_equal(
221 typename std::iterator_traits<Itr1>::iterator_category{},
222 first_start,
223 first_end,
224 typename std::iterator_traits<Itr2>::iterator_category{},
225 second_start,
226 second_end,
227 std::move(cmp)
228 );
229 }
230};
231
232} // namespace equal_detail
233// parasoft-begin-suppress AUTOSAR-M7_3_3-a "An unnamed namespace is used to create a per-TU reference to a global
234// object used in multiple TUs."
235// parasoft-begin-suppress CERT_CPP-DCL59-a "An unnamed namespace is used to create a per-TU reference to a global
236// object used in multiple TUs."
237ARENE_CPP14_INLINE_VARIABLE(equal_detail::equal_fn, equal);
238// parasoft-end-suppress AUTOSAR-M7_3_3-a
239// parasoft-end-suppress CERT_CPP-DCL59-a
240
241} // namespace base
242} // namespace arene
243// parasoft-end-suppress AUTOSAR-A2_8_1-a-2
244#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_ALGORITHM_EQUAL_HPP_
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10