MySQL 9.6.0
Source Code Documentation
disjoint_pairs.h
Go to the documentation of this file.
1// Copyright (c) 2024, 2025, Oracle and/or its affiliates.
2//
3// This program is free software; you can redistribute it and/or modify
4// it under the terms of the GNU General Public License, version 2.0,
5// as published by the Free Software Foundation.
6//
7// This program is designed to work with certain software (including
8// but not limited to OpenSSL) that is licensed under separate terms,
9// as designated in a particular file or component or in included license
10// documentation. The authors of MySQL hereby grant you an additional
11// permission to link the program and your derivative works with the
12// separately licensed software that they have either included with
13// the program or referenced in the documentation.
14//
15// This program is distributed in the hope that it will be useful,
16// but WITHOUT ANY WARRANTY; without even the implied warranty of
17// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18// GNU General Public License, version 2.0, for more details.
19//
20// You should have received a copy of the GNU General Public License
21// along with this program; if not, write to the Free Software
22// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
23
24#ifndef MYSQL_RANGES_DISJOINT_PAIRS_H
25#define MYSQL_RANGES_DISJOINT_PAIRS_H
26
27/// @file
28/// Experimental API header
29
30/// @addtogroup GroupLibsMysqlRanges
31/// @{
32
33#include <iterator> // iterator_traits
34#include <ranges> // view_base
35#include <utility> // declval
36#include "my_compiler.h" // MY_COMPILER_DIAGNOSTIC_PUSH
37#include "mysql/iterators/iterator_interface.h" // Iterator_interface
38#include "mysql/ranges/collection_interface.h" // Collection_interface
39#include "mysql/ranges/view_sources.h" // View_source
40
41namespace mysql::ranges::detail {
42
43struct Make_pair {
44 /// Return a pair from the given arguments.
45 ///
46 /// The component types will be references if the arguments are lvalue
47 /// references, and values if the arguments are rvalue references or values.
48 template <class Type_t>
49 constexpr static std::pair<Type_t &, Type_t &> make_pair(Type_t &first,
50 Type_t &second) {
51 return {first, second};
52 }
53
54 template <class Type_t>
55 constexpr static std::pair<Type_t, Type_t> make_pair(const Type_t &first,
56 const Type_t &second) {
57 return {first, second};
58 }
59};
60
61} // namespace mysql::ranges::detail
62namespace mysql::ranges {
63
64/// Iterator used by Disjoint_pairs_interface and Disjoint_pairs_view: this
65/// yields the disjoint, adjacent pairs of values from the source iterator.
66///
67/// This caches two iterator positions internally. It returns the pairs by
68/// value.
69///
70/// @tparam Source_iterator_tp The source iterator.
71///
72/// @tparam Make_pair_tp Function object that creates a pair from two input
73/// values. By default, uses a function object that creates std::pair objects.
74template <std::forward_iterator Source_iterator_tp,
75 class Make_pair_tp = detail::Make_pair>
78 Disjoint_pairs_iterator<Source_iterator_tp, Make_pair_tp>> {
79 public:
80 using Source_iterator_t = Source_iterator_tp;
81 using Make_pair_t = Make_pair_tp;
83 using Value_t = decltype(Make_pair_t::make_pair(
84 std::declval<Source_value_t>(), std::declval<Source_value_t>()));
85
86 /// Default constructor, which leaves the object in a state that is not
87 /// usable, except it can be assigned to. Provided because std::input_iterator
88 /// requires std::default_initializable.
90
91 /// Construct a new iterator, where the first component points to the given
92 /// position.
94 : m_first(position), m_second{} {}
95
96 /// @return the current value.
97 [[nodiscard]] Value_t get() const {
98 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119592
100 MY_COMPILER_GCC_DIAGNOSTIC_IGNORE("-Wmaybe-uninitialized")
101 if (!m_second.has_value()) {
102 m_second = std::ranges::next(m_first);
103 }
104 return Make_pair_t::make_pair(*m_first, *m_second.value());
106 }
107
108 /// Move to the next position.
109 void next() {
110// If we enable this optimization in gcc, it produces spurious
111// -Wmaybe-uninitialized warnings, likely due to
112// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119592 . The warnings are in
113// functions that use classes that inherit from Disjoint_pairs_iterator, and
114// MY_COMPILER_GCC_DIAGNOSTIC_IGNORE in the current function does not
115// silence the warning. Therefore, enabling the optimization in gcc would
116// make the class hard to use, so instead we disable the optimization until
117// gcc has been fixed. Unfortunately, clang defines __GNUC__, so in order to
118// not disable the optimization on clang we also check if __clang__ is
119// defined.
120#if !defined(__GNUC__) || defined(__clang__)
121 if (m_second.has_value()) {
122 m_first = std::next(m_second.value());
123 } else {
124 std::ranges::advance(m_first, 2);
125 }
126#else
127 std::ranges::advance(m_first, 2);
128#endif
129 m_second.reset();
130 }
131
132 /// Move to the previous position.
133 void prev()
134 requires std::bidirectional_iterator<Source_iterator_t>
135 {
136 // Not std::advance, since that is undefined, since this iterator's value
137 // type is not a reference, so that it does not model
138 // LegacyBidirectionalIterator.
139 std::ranges::advance(m_first, -2);
140 m_second.reset();
141 }
142
143 /// Move the iterator the given number of steps.
144 void advance(std::ptrdiff_t delta)
145 requires std::random_access_iterator<Source_iterator_t>
146 {
147 m_first += 2 * delta;
148 m_second.reset();
149 }
150
151 /// @return the number of steps from the other iterator to this iterator.
152 [[nodiscard]] std::ptrdiff_t distance_from(
153 const Disjoint_pairs_iterator &other) const
154 requires std::random_access_iterator<Source_iterator_t>
155 {
156 return (m_first - other.m_first) >> 1;
157 }
158
159 /// @return true if this iterator equals the other iterator.
160 [[nodiscard]] bool is_equal(const Disjoint_pairs_iterator &other) const {
161 return m_first == other.m_first;
162 }
163
164 private:
165 /// Iterator to the first position.
167
168 /// Iterator to the second position.
169 ///
170 /// This is mutable because it is only a cache and gets updated lazily.
171 ///
172 /// (We cannot update this member when advancing the iterator, because that
173 /// would make it advance past the past-the-end iterator, which is undefined
174 /// behavior. Instead we unset it, and initialize it on the next dereference
175 /// operation.)
176 mutable std::optional<Source_iterator_t> m_second;
177}; // class Disjoint_pairs_iterator
178
179/// Factory function to create a Disjoint_pairs_iterator.
180template <class Pair_t = detail::Make_pair, class Iterator_t>
181[[nodiscard]] auto make_disjoint_pairs_iterator(const Iterator_t &position) {
183}
184
185/// CRTP base used to define classes that yield disjoint, adjacent pairs of
186/// elements from an even-length source sequence.
187///
188/// For example, if the source sequence is 2, 3, 5, 7, 11, 13, then this
189/// yields the pairs <2,3>, <5,7>, <11,13>. It is conceptually similar to
190/// std::stride_view<std::slide_view<Source_tp>>, except the window
191/// width is defined at compile time and each window is wrapped in an object.
192///
193/// This is for objects that own the source. If you need objects that
194/// do not own the source - a *view* - use Disjoint_pairs_view.
195///
196/// @tparam Self_tp Class that derives from this class. It must implement the
197/// member function disjoint_pairs_source(), returning a reference to an object
198/// with the member functions `begin`, `end`, `empty`, and `size`. The distance
199/// between `begin` and `end` must be even.
200///
201/// @tparam Make_pair_tp Class containing a static member function `make_pair`
202/// that defines how to construct a pair from two adjacent elements. By default,
203/// uses `detail::Make_pair`, for which `make_pair` constructs and returns a
204/// `std::pair` object.
205template <class Self_tp, class Make_pair_tp>
207 : public mysql::ranges::Collection_interface<Self_tp> {
208 using Self_t = Self_tp;
210
211 public:
212 using Make_pair_t = Make_pair_tp;
213
214 /// Return const iterator to the beginning.
215 [[nodiscard]] auto begin() const {
216 return make_disjoint_pairs_iterator<Make_pair_t>(source().begin());
217 }
218
219 /// Return const iterator to sentinel.
220 [[nodiscard]] auto end() const {
221 return make_disjoint_pairs_iterator<Make_pair_t>(source().end());
222 }
223
224 /// Return iterator to the beginning.
225 [[nodiscard]] auto begin() {
226 return make_disjoint_pairs_iterator<Make_pair_t>(source().begin());
227 }
228
229 /// Return iterator to sentinel.
230 [[nodiscard]] auto end() {
231 return make_disjoint_pairs_iterator<Make_pair_t>(source().end());
232 }
233
234 /// Return true if the range is empty.
235 ///
236 /// Use `Collection_interface::empty` if
237 /// `Self_t::disjoint_pairs_source().empty()` does not exist.
238 [[nodiscard]] bool empty() const {
239 // On older versions of gcc and clang we could use `using Base_t::empty`
240 // instead of defining this function, but not on gcc > 14 and clang > 17:
241 // see
242 // https://stackoverflow.com/questions/79552469/constraint-does-not-disambiguate-function-in-base-class-from-function-in-derived
243 return Base_t::empty();
244 }
245
246 /// Return true if the range is empty.
247 ///
248 /// Use `Self_t::disjoint_pairs_source().empty()` if it exists.
249 [[nodiscard]] bool empty() const
250 requires requires(Self_t s) { s.disjoint_pairs_source().empty(); }
251 {
252 return source().empty();
253 }
254
255 /// Return the number of pairs, i.e., half the size of the source.
256 ///
257 /// Use `Collection_interface::size` if
258 /// `Self_t::disjoint_pairs_source().size()` does not exist.
259 [[nodiscard]] auto size() const {
260 // See comment in empty above.
261 return Base_t::size();
262 }
263
264 /// Return the number of pairs, i.e., half the size of the source.
265 ///
266 /// Use `Self_t::disjoint_pairs_source().size()` if it exists.
267 [[nodiscard]] auto size() const
268 requires requires(Self_t s) { s.disjoint_pairs_source().size(); }
269 {
270 return source().size() >> 1;
271 }
272
273 private:
274 [[nodiscard]] const auto &source() const {
275 return static_cast<const Self_t *>(this)->disjoint_pairs_source();
276 }
277 [[nodiscard]] auto &source() {
278 return static_cast<Self_t *>(this)->disjoint_pairs_source();
279 }
280}; // class Disjoint_pairs_interface
281
282/// View over an even-length sequence, yielding the disjoint, adjacent pairs of
283/// elements.
284///
285/// For example, if the source sequence is 2, 3, 5, 7, 11, 13, then this
286/// yields the pairs <2,3>, <5,7>, <11,13>. It is conceptually similar to
287/// std::stride_view<std::slide_view<Source_tp>>, except the window
288/// width is defined at compile time and each window is wrapped in an object.
289///
290/// This a view, which does not own the source. If you need to define
291/// a class that owns the source, use Disjoint_pairs_interface.
292///
293/// @tparam Source_tp Range that this is a view over. It must have the
294/// member functions `begin`, `end`, `empty`, and `size`. The distance between
295/// `begin` and `end` must be even.
296///
297/// @tparam Make_pair_tp Class containing a static member function `make_pair`
298/// that defines how to construct a pair from two adjacent elements. By default,
299/// uses `detail::Make_pair`, for which `make_pair` constructs and returns a
300/// `std::pair` object.
301template <class Source_tp, class Make_pair_tp = detail::Make_pair>
304 Disjoint_pairs_view<Source_tp, Make_pair_tp>, Make_pair_tp>,
305 public std::ranges::view_base {
307
308 public:
309 using Source_t = Source_tp;
310 using Make_pair_t = Make_pair_tp;
317
318 // Cannot default-construct in case the source is a view type (since
319 // we use View_source).
321
322 /// Construct a view that over the given source.
323 ///
324 /// The caller must ensure that the source outlives this object.
326
327 // Defaults for rule-of-5 members
333
334 /// Return const reference to the source.
336
337 private:
338 /// source, either owned or not.
340}; // Disjoint_pairs_view
341
342/// Factory to construct a Disjoint_pairs_view from a given range.
343///
344/// @tparam Make_pair_t Class containing a static member function `make_pair`
345/// that defines how to construct a pair from two adjacent elements. By default,
346/// uses `detail::Make_pair`, for which `make_pair` constructs and returns a
347/// `std::pair` object.
348///
349/// @tparam Source_t Range that this is a view over. It must have the
350/// member functions `begin`, `end`, `empty`, and `size`. The distance between
351/// `begin` and `end` must be even.
352///
353/// @return New Disjoint_pairs_view object.
354template <class Make_pair_t = detail::Make_pair, class Source_t>
355[[nodiscard]] auto make_disjoint_pairs_view(const Source_t &source) {
357}
358
359} // namespace mysql::ranges
360
361// addtogroup GroupLibsMysqlRanges
362/// @}
363
364#endif // ifndef MYSQL_RANGES_DISJOINT_PAIRS_H
CRTP base class (mixin) that makes your class a standard-compliant iterator, given only a minimal set...
Definition: iterator_interface.h:370
CRTP base class to provide members of a collection based on an implementation that provides begin/end...
Definition: collection_interface.h:90
constexpr auto size() const
Return the number of elements in this view, unsigned (size_t), by computing std::ranges::distance(beg...
Definition: collection_interface.h:145
constexpr bool empty() const
Return true if the range is empty, i.e., begin() == end().
Definition: collection_interface.h:133
Self_tp Self_t
Definition: collection_interface.h:91
CRTP base used to define classes that yield disjoint, adjacent pairs of elements from an even-length ...
Definition: disjoint_pairs.h:207
auto size() const
Return the number of pairs, i.e., half the size of the source.
Definition: disjoint_pairs.h:267
bool empty() const
Return true if the range is empty.
Definition: disjoint_pairs.h:238
auto begin()
Return iterator to the beginning.
Definition: disjoint_pairs.h:225
auto & source()
Definition: disjoint_pairs.h:277
bool empty() const
Return true if the range is empty.
Definition: disjoint_pairs.h:249
auto begin() const
Return const iterator to the beginning.
Definition: disjoint_pairs.h:215
auto end() const
Return const iterator to sentinel.
Definition: disjoint_pairs.h:220
auto size() const
Return the number of pairs, i.e., half the size of the source.
Definition: disjoint_pairs.h:259
const auto & source() const
Definition: disjoint_pairs.h:274
auto end()
Return iterator to sentinel.
Definition: disjoint_pairs.h:230
Make_pair_tp Make_pair_t
Definition: disjoint_pairs.h:212
Iterator used by Disjoint_pairs_interface and Disjoint_pairs_view: this yields the disjoint,...
Definition: disjoint_pairs.h:78
Source_iterator_t m_first
Iterator to the first position.
Definition: disjoint_pairs.h:166
std::ptrdiff_t distance_from(const Disjoint_pairs_iterator &other) const
Definition: disjoint_pairs.h:152
Value_t get() const
Definition: disjoint_pairs.h:97
void prev()
Move to the previous position.
Definition: disjoint_pairs.h:133
Make_pair_tp Make_pair_t
Definition: disjoint_pairs.h:81
Source_iterator_tp Source_iterator_t
Definition: disjoint_pairs.h:80
bool is_equal(const Disjoint_pairs_iterator &other) const
Definition: disjoint_pairs.h:160
mysql::ranges::Iterator_value_type< Source_iterator_t > Source_value_t
Definition: disjoint_pairs.h:82
void advance(std::ptrdiff_t delta)
Move the iterator the given number of steps.
Definition: disjoint_pairs.h:144
std::optional< Source_iterator_t > m_second
Iterator to the second position.
Definition: disjoint_pairs.h:176
void next()
Move to the next position.
Definition: disjoint_pairs.h:109
Disjoint_pairs_iterator() noexcept=default
Default constructor, which leaves the object in a state that is not usable, except it can be assigned...
decltype(Make_pair_t::make_pair(std::declval< Source_value_t >(), std::declval< Source_value_t >())) Value_t
Definition: disjoint_pairs.h:84
View over an even-length sequence, yielding the disjoint, adjacent pairs of elements.
Definition: disjoint_pairs.h:305
Make_pair_tp Make_pair_t
Definition: disjoint_pairs.h:310
Disjoint_pairs_view(const Source_t &source)
Construct a view that over the given source.
Definition: disjoint_pairs.h:325
Disjoint_pairs_view(const Disjoint_pairs_view &)=default
Source_ref_t m_source
source, either owned or not.
Definition: disjoint_pairs.h:339
const Source_t & disjoint_pairs_source() const
Return const reference to the source.
Definition: disjoint_pairs.h:335
Disjoint_pairs_view & operator=(const Disjoint_pairs_view &)=default
Source_tp Source_t
Definition: disjoint_pairs.h:309
Disjoint_pairs_view(Disjoint_pairs_view &&)=default
mysql::ranges::Range_iterator_type< Source_t > Source_iterator_t
Definition: disjoint_pairs.h:311
Disjoint_pairs_view & operator=(Disjoint_pairs_view &&)=default
mysql::ranges::Range_const_iterator_type< Source_t > Source_const_iterator_t
Definition: disjoint_pairs.h:313
Wrapper around an object that is the source for a view: the wrapped object is owned by this object if...
Definition: view_sources.h:101
const Source_t & reference() const
Return a reference to the stored object.
Definition: view_sources.h:130
Experimental API header.
Experimental API header.
Header for compiler-dependent features.
#define MY_COMPILER_GCC_DIAGNOSTIC_IGNORE(X)
Definition: my_compiler.h:242
#define MY_COMPILER_DIAGNOSTIC_PUSH()
save the compiler's diagnostic (enabled warnings, errors, ...) state
Definition: my_compiler.h:277
#define MY_COMPILER_DIAGNOSTIC_POP()
restore the compiler's diagnostic (enabled warnings, errors, ...) state
Definition: my_compiler.h:278
Definition: buffer_interface.h:40
Definition: buffer_interface.h:40
std::remove_cvref_t< decltype(std::declval< const Range_t >().begin())> Range_const_iterator_type
Gives the const_iterator type, deduced from the begin() const member.
Definition: meta.h:47
auto make_disjoint_pairs_iterator(const Iterator_t &position)
Factory function to create a Disjoint_pairs_iterator.
Definition: disjoint_pairs.h:181
std::remove_cvref_t< decltype(*std::declval< Iterator_t >())> Iterator_value_type
Gives the value type for any iterator type, deduced from operator *.
Definition: meta.h:63
std::remove_cvref_t< decltype(std::declval< Range_t >().begin())> Range_iterator_type
Gives the iterator type, deduced from the begin() member.
Definition: meta.h:42
auto make_disjoint_pairs_view(const Source_t &source)
Factory to construct a Disjoint_pairs_view from a given range.
Definition: disjoint_pairs.h:355
noexcept
The return type for any call_and_catch(f, args...) call where f(args...) returns Type.
Definition: call_and_catch.h:76
Define std::hash<Gtid>.
Definition: gtid.h:355
repeated Source source
Definition: replication_asynchronous_connection_failover.proto:42
Definition: disjoint_pairs.h:43
constexpr static std::pair< Type_t, Type_t > make_pair(const Type_t &first, const Type_t &second)
Definition: disjoint_pairs.h:55
constexpr static std::pair< Type_t &, Type_t & > make_pair(Type_t &first, Type_t &second)
Return a pair from the given arguments.
Definition: disjoint_pairs.h:49
Experimental API header.