MySQL 9.6.0
Source Code Documentation
iterator_interface.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_ITERATORS_ITERATOR_INTERFACE_H
25#define MYSQL_ITERATORS_ITERATOR_INTERFACE_H
26
27/// @file
28/// Experimental API header
29
30#include <cstddef> // ptrdiff_t
31#include <iterator> // input_iterator_tag
32#include <type_traits> // remove_cvref
33#include "mysql/meta/is_pointer.h" // Is_pointer
34#include "mysql/meta/not_decayed.h" // Not_decayed
35
36/// @addtogroup GroupLibsMysqlIterators
37/// @{
38
40
41// ==== Concepts to detect specific member functions ====
42//
43// These concepts are used to deduce the iterator category and iterator
44// concepts.
45
46/// Helper: returns true if Type has a get function, regardless if it returns
47/// void or not.
48template <class Type>
49concept Has_member_get_maybe_void = requires(Type t) { t.get(); };
50
51/// Helper: returns true if Type has a get function that returns void (which
52/// does not make it an iterator).
53template <class Type>
54concept Has_member_get_void = requires(Type t) {
55 { t.get() } -> std::same_as<void>;
56 };
57
58/// true if `Type` has a `get` member that does not return void.
59template <class Type>
62
63/// true if `Type` has a `get` member that returns a pointer.
64template <class Type>
65concept Has_member_get_pointer = // this comment helps clang-format
66 requires(Type t) {
67 { t.get_pointer() } -> mysql::meta::Is_pointer;
68 };
69
70/// true if `Type` has a `get` member that returns a reference type.
71template <class Type>
73 std::is_reference_v<decltype(std::declval<Type>().get())>;
74
75/// true if `Type` has a `next` member.
76template <class Type>
77concept Has_member_next = requires(Type t) { t.next(); };
78
79/// true if `Type` has an `is_equal` member.
80template <class Type>
81concept Has_member_is_equal = requires(Type t, const Type &other) {
82 { t.is_equal(other) } -> std::same_as<bool>;
83 };
84
85/// true if `Type` has an `is_sentinel` member.
86template <class Type>
87concept Has_member_is_sentinel = requires(Type t) {
88 { t.is_sentinel() } -> std::same_as<bool>;
89 };
90
91/// true if `Type` has a `prev` member
92template <class Type>
93concept Has_member_prev = requires(Type t) { t.prev(); };
94
95/// true if `Type` has an `advance` member
96template <class Type>
98 requires(Type t, std::ptrdiff_t x) { t.advance(x); };
99
100/// true if `Type` has a `distance_from` member
101template <class Type>
102concept Has_member_distance_from = // this comment helps clang-format
103 requires(Type t, const Type &other) {
104 { t.distance_from(other) } -> std::same_as<std::ptrdiff_t>;
105 };
106
107/// true if `Type` has a `distance_from` member
108template <class Type>
109concept Has_member_distance_from_sentinel = // this comment helps clang-format
110 requires(Type t) {
111 { t.distance_from_sentinel() } -> std::same_as<std::ptrdiff_t>;
112 };
113
114/// true if `Type` has an `is_equal` or `distance_from` member.
115template <class Type>
118
119} // namespace mysql::iterators::detail
120
121// ==== Concepts to check member functions defining iterator categories ====
122
123namespace mysql::iterators {
124
125/// True if `Type` has the members required for `Iterator_interface<Type>` to
126/// satisfy `std::input_iterator`. Note that this is weaker than
127/// LegacyInputIterator; see Is_legacy_input_iterator_impl.
128template <class Type>
129concept Is_input_iterator_impl = // this comment helps clang-format
132
133/// True if `Type` has the members required for `Iterator_interface<Type>` to
134/// meet the syntactic requirements for LegacyInputIterator.
135template <class Type>
138
139/// True if `Type` has the members and the value type for required for
140/// `Iterator_interface<Type>` to meet the syntactic requirements for
141/// LegacyForwardIterator.
142template <class Type>
147 std::copyable<Type>;
148
149/// true if `Type` has the members required for `Iterator_interface<Type>` to
150/// meet the syntactic requirements for `LegacyBidirectionalIterator`.
151template <class Type>
155
156/// true if `Type` has the members required for `Iterator_interface<Type>` to
157/// meet the syntactic requirements for `LegacyRandomAccessIterator`.
158template <class Type>
162
163/// true if `Type` has the members required for `Iterator_interface<Type>` to
164/// meet the syntactic requirements for `LegacyContiguousIterator`.
165template <class Type>
169
170} // namespace mysql::iterators
171
172// ==== Arrow proxy ====
173
174namespace mysql::iterators::detail {
175
176/// Auxiliary object that holds a value internally, and operator-> returns a
177/// pointer to the value. This is also called an "arrow proxy".
178///
179/// This is useful to implement the `operator->` for iterator classes for which
180/// `operator*` returns by value, rather than by reference.
181template <class Value_tp>
183 public:
184 using Value_t = Value_tp;
185
186 template <class... Args_t>
188 Args_t...>
189 explicit Dereferenceable_wrapper(Args_t &&...args)
190 : m_value(std::forward<Args_t>(args)...) {}
191
192 Value_t *operator->() { return &m_value; }
193
194 private:
196}; // class Dereferenceable_wrapper
197
198} // namespace mysql::iterators::detail
199
200// ==== Default_sentinel ====
201
202namespace mysql::iterators {
203
204/// Used like std::default_sentinel_t / std::default_sentinel.
205///
206/// Currently we support compiler versions that have not yet implemented
207/// std::default_sentinel_t / std::default_sentinel, so we define our own
208/// sentinel type.
209///
210/// Once we drop support for such old compilers, please remove this and use
211/// std::default_sentinel_t / std::default_sentinel instead.
213 public:
214 auto operator<=>(const Default_sentinel &) const = default;
215 bool operator==(const Default_sentinel &) const = default;
216};
218
219// ==== Iterator_interface ====
220
221/// CRTP base class (mixin) that makes your class a standard-compliant iterator,
222/// given only a minimal set of functions to read, move and compare iterators.
223///
224/// Based on the member functions you define, this class deduces all the
225/// operators, as well as the iterator traits. This ensures that your class will
226/// meet the appropriate named requirement, `LegacyInputIterator`,
227/// `LegacyForwardIterator`, `LegacyBidirectionalIterator`,
228/// `LegacyRandomAccessIterator`, or `LegacyContiguousIterator`, as well as
229/// satisfy the appropriate concept, `std::input_iterator`,
230/// `std::forward_iterator`, `std::bidirectional_iterator`,
231/// `std::random_access_iterator`, or `std::contiguous_iterator`.
232///
233/// Defining member functions
234/// =========================
235///
236/// To make `It` an iterator that iterates over values of type `V`, inherit
237/// like:
238///
239/// @code
240/// class It : public Iterator_interface<It> {
241/// public:
242/// /* define member functions as described below */
243/// };
244/// @endcode
245///
246/// `It` must be default-constructible, copy/move-constructible, and
247/// copy/move-assignable. In addition, define a subset of the following
248/// member functions:
249///
250/// @code
251/// // Exactly one of the following, to read the current value:
252/// V get() const;
253/// V &get() const;
254/// V *get_pointer() const;
255///
256/// // At least one of next and advance to move the position; prev is optional.
257/// void next();
258/// void prev();
259/// void advance(std::ptrdiff_t);
260///
261/// // Optionally one of the following, to compare iterators:
262/// bool is_equal(const It &) const;
263/// std::ptrdiff_t distance_from(const It &) const;
264/// bool is_sentinel() const;
265/// std::ptrdiff_t distance_from_sentinel() const;
266/// @endcode
267///
268/// C++ defines two hierarchies of iterators, which are confusingly similar and
269/// subtly different:
270///
271/// - Pre-C++20 named requirements such as `LegacyInputIterator`, which can be
272/// queried at compile-time using
273/// `std::iterator_traits<It>::iterator_category`.
274///
275/// - C++20 concepts such as `std::input_iterator`, which can be queried at
276/// compile-time using these concepts.
277///
278/// This class deduces both the iterator category and the iterator concept,
279/// as follows:
280///
281/// - `LegacyInputIterator` requries any `get` or `get_pointer` function, either
282/// `next` or `advance`, and either `is_equal` or `distance_from`.
283///
284/// - `LegacyForwardIterator` requries `LegacyInputIterator`, and that `get`
285/// returns by reference, and the class must be copyable.
286///
287/// - `LegacyBidirectionalIterator` requires `LegacyForwardIterator`, and either
288/// `prev` or `advance`.
289///
290/// - `LegacyRandomAccessIterator` requries `LegacyBidirectionalIterator`, and
291/// `advance`, and `distance_from`.
292///
293/// - `LegacyContiguousIterator` requries `LegacyRandomAccessIterator`, and
294/// requires `get_pointer`.
295///
296/// - `std::input_iterator` requries any `get` or `get_pointer` function, and
297/// either `next` or `advance`. (It is weaker than LegacyInputIterator because
298/// it does not require that iterators can be compared.)
299///
300/// - `std::forward_iterator` requries `std::input_iterator`, and either
301/// `is_equal` or `distance_from`, and the class must be copyable. (It is
302/// weaker than LegacyForwardIterator because it does not require that `get`
303/// returns by reference.)
304///
305/// - `std::bidirectional_iterator` requries `std::forward_iterator`, and either
306/// `prev` or `advance`. (It is weaker than LegacyBidirectionalIterator
307/// because it does not require that `get` returns by reference.)
308///
309/// - `std::random_access_iterator` requires `std::bidirectional_iterator`, and
310/// `advance` and `distance_from`. (It is weaker than
311/// LegacyRandomAccessIterator because it does not require that `get` returns
312/// by reference.)
313///
314/// - `std::contiguous_iterator` requires `std::random_access_iterator`, and
315/// requires `get_pointer`. This coincides with the requirements for
316/// `LegacyContiguousIterator`.
317///
318/// * Diagram of concept/category strengths
319///
320/// To summarize the previous section, the following diagram illustrates the
321/// relative strengths between deduced iterator concepts and categories for
322/// types derived from this class. The notation A-->B indicates that B is
323/// stronger that A, i.e., requires everything that A requires and more. The
324/// abbreviations I/F/B/R/C/ct/cy mean
325/// input/forward/bidirectional/random_access/contiguous/concept/category,
326/// respectively.
327///
328///```
329/// 1 2 4 5
330/// I_ct ----> I_cy ----> F_ct ----> B_ct ----> R_ct
331/// | | |
332/// 3| 3| 3|
333/// V 4 V 5 V 6
334/// F_cy ----> B_cy ----> R_cy ----> C_ct==C_cy
335///```
336///
337/// Each arrow is annotated by a number that refers to the following list,
338/// indicating what you need to implement to "follow the arrow":
339/// (1) Implement `is_equal` to make iterators equality-comparable.
340/// (2) Implement the copy constructor (actually, just don't delete it).
341/// (3) Make `get` return by reference.
342/// (4) Implement `prev` to enable moving backwards.
343/// (5) Implement `advance` and `distance_from` instead of
344/// `get`/`next`/`is_equal`, to make it possible to take long steps.
345/// (6) Implement `get_pointer` and ensure that returned objects are adjacent
346/// in memory.
347///
348/// * Iterators returning values, not references
349///
350/// Iterators that return value rather than reference can't meet the
351/// `LegacyForwardIterator` requirement. This determines the behavior of
352/// standard algorithms like `std::prev`, `std::advance`, and `std::distance`.
353/// Thus, just because the iterator returns by value, both `std::advance(it,
354/// negative_number)` and `std::prev` produce undefined behavior (typically an
355/// infinite loop), and `std::distance` is linear-time (even if the iterator
356/// satisfies `std::random_access_iterator`). Use `std::ranges::prev`,
357/// `std::ranges::advance`, and `std::ranges::distance` instead.
358///
359/// * Sentinel types
360///
361/// If your iterator needs a sentinel type, this class limits it to be the
362/// mysql::iterator::Default_sentinel type. Define one or both of the member
363/// functions `is_sentinel` or `distance_from_sentinel`.
364///
365/// @note Thanks for inspiration from
366/// https://vector-of-bool.github.io/2020/06/13/cpp20-iter-facade.html
367///
368/// @tparam Self_tp The subclass that inherits from this class.
369template <class Self_tp>
371 protected:
372 using Self_t = Self_tp;
373
374 public:
375 // ==== input_iterator members ====
376
377 /// Dereference operator, which returns the current value.
378 ///
379 /// This delegates the work to `get`.
380 [[nodiscard]] decltype(auto) operator*() const {
381 if constexpr (detail::Has_member_get<Self_t>) {
382 return self().get();
383 } else {
384 return *self().get_pointer();
385 }
386 }
387
388 /// Arrow operator, return a pointer (possibly a fancy pointer) to the current
389 /// element.
390 ///
391 /// This delegates work to `get_pointer` if that is defined. Otherwise, if
392 /// `get` returns a reference, returns the address of `get()`. Otherwise,
393 /// returns an "arrow proxy": an object that stores a copy of the value and
394 /// for which the arrow operator returns the address of the stored value. Note
395 /// that the pointer returned from the arrow proxy only lives as long as the
396 /// arrow proxy lives.
397 [[nodiscard]] auto operator->() const {
399 return self().get_pointer();
400 } else {
401 decltype(auto) ret = **this;
402 if constexpr (std::is_reference_v<decltype(ret)>) {
403 return std::addressof(ret);
404 } else {
406 std::move(ret));
407 }
408 }
409 }
410
411 /// Pre-increment operator, which advances the position one step and returns a
412 /// reference to the iterator itself.
413 ///
414 /// This delegates the work to the `next` member function if there is one;
415 /// otherwise to the `advance` member function.
417 if constexpr (detail::Has_member_next<Self_t>) {
418 self().next();
419 } else {
420 self().advance(1);
421 }
422 return self();
423 }
424
425 /// Post-increment operator, which advances the position one step. For forward
426 /// iterators and higher, returns a copy of the iterator before the increment.
427 /// For input iterators, returns a reference to the iterator itself.
428 ///
429 /// This delegates the work to the `next` member function if there is one;
430 /// otherwise to the `advance` member function.
431 auto operator++(int) {
432 if constexpr (std::copyable<Self_t>) {
433 auto ret = self();
434 ++*this;
435 return ret;
436 } else {
437 // For non-copyable iterators (which are necessarily single-pass, hence
438 // at most input iterators), just return void.
439 ++*this;
440 }
441 }
442
443 // ===== bidirectional_iterator members ====
444
445 /// Pre-decrement iterator, which moves one step back and returns a reference
446 /// to the iterator itself.
447 ///
448 /// This delegates the work to the `prev` member function if there is one;
449 /// otherwise to the `advance` member function.
453 {
454 if constexpr (detail::Has_member_prev<Self_t>) {
455 self().prev();
456 } else {
457 self().advance(-1);
458 }
459 return self();
460 }
461
462 /// Post-decrement operator, which moves one step back and returns a copy of
463 /// the iterator before the decrement.
464 ///
465 /// This delegates the work to the `prev` member function if there is one;
466 /// otherwise to the `advance` member function.
467 auto operator--(int)
470 {
471 if constexpr (std::copyable<Self_t>) {
472 auto ret = self();
473 --*this;
474 return ret;
475 } else {
476 // For non-copyable iterators (which are necessarily single-pass, hence
477 // at most input iterators), just return void.
478 --*this;
479 }
480 }
481
482 // ===== random_access_iterator members ====
483
484 /// Addition assignment operator, which moves the iterator forward by the
485 /// given number of steps, and returns a reference to the iterator itself.
486 ///
487 /// This delegates the work to `advance`.
488 Self_t &operator+=(std::ptrdiff_t delta)
490 {
491 self().advance(delta);
492 return self();
493 }
494
495 /// Subtraction assignment operator, which moves the iterator backward by the
496 /// given number of steps, and returns a reference to the iterator itself.
497 ///
498 /// This delegates the work to `advance`.
499 Self_t &operator-=(std::ptrdiff_t delta)
501 {
502 return (*this += -delta);
503 }
504
505 /// Addition operator, which returns a new iterator that is the given number
506 /// of steps ahead of the current iterator.
507 ///
508 /// This delegates the work to `advance`.
509 [[nodiscard]] Self_t operator+(std::ptrdiff_t delta) const
511 {
512 Self_t ret(self());
513 ret.advance(delta);
514 return ret;
515 }
516
517 /// Subtraction-of-integer operator, which returns a new iterator that is the
518 /// given number of steps behind of the current iterator.
519 ///
520 /// This delegates the work to `advance`.
521 [[nodiscard]] Self_t operator-(std::ptrdiff_t delta) const
523 {
524 return (*this + -delta);
525 }
526
527 /// Subtraction-of-iterator operator, which returns the number of steps from
528 /// other this.
529 ///
530 /// This delegates the work to `distance_from`.
531 [[nodiscard]] std::ptrdiff_t operator-(const Self_t &other) const
533 {
534 return self().distance_from(other);
535 }
536
537 /// Subscript operator, which returns a new iterator that is the given number
538 /// of steps ahead of the current iterator.
539 ///
540 /// This delegates the work to `advance`.
541 [[nodiscard]] decltype(auto) operator[](std::ptrdiff_t delta) const
543 {
544 return *(*this + delta);
545 }
546
547 private:
548 /// Return a const reference to the subclass.
549 [[nodiscard]] const Self_t &self() const {
550 return static_cast<const Self_t &>(*this);
551 }
552
553 /// Return a non-const reference to the subclass.
554 [[nodiscard]] Self_t &self() { return static_cast<Self_t &>(*this); }
555}; // class Iterator_interface
556
557// ==== Out-of-class operator definitions ====
558
559/// Equality operator, which returns true if the two iterators are equal.
560///
561/// This delegates the work to the member function `is_equal` if there is one;
562/// otherwise to `distance_from`.
563template <class Iterator_t>
564 requires std::derived_from<Iterator_t, Iterator_interface<Iterator_t>> &&
565 detail::Has_equality_member<Iterator_t>
566[[nodiscard]] bool operator==(const Iterator_t &a, const Iterator_t &b) {
568 return a.is_equal(b);
569 } else {
570 return a.distance_from(b) == 0;
571 }
572}
573
574/// Equality operator, which returns true if the iterator is equal to the
575/// sentinel.
576///
577/// This delegates the work to the member function `is_equal` if there is one;
578/// otherwise to `distance_from`.
579template <class Iterator_t>
580 requires std::derived_from<Iterator_t, Iterator_interface<Iterator_t>> &&
581 (
582 requires { Iterator_t().distance_from_sentinel(); } ||
583 requires { Iterator_t().is_sentinel(); })
584[[nodiscard]] bool operator==(const Iterator_t &it, const Default_sentinel &) {
586 return it.is_sentinel();
587 } else {
588 return it.distance_from_sentinel() == 0;
589 }
590}
591
592/// Addition operator with the left-hand-side of type ptrdiff_t and the
593/// right-hand-side of Iterator type, returning a new iterator that is ahead of
594/// the given iterator by the given number of steps.
595///
596/// This delegates work to `advance`.
597template <class Iterator_t>
598 requires std::derived_from<Iterator_t, Iterator_interface<Iterator_t>> &&
599 detail::Has_member_advance<Iterator_t>
600[[nodiscard]] Iterator_t operator+(std::ptrdiff_t delta,
601 const Iterator_t &iterator) {
602 return iterator + delta;
603}
604
605/// Subtraction operator with the left-hand-side of Iterator type and the
606/// right-hand-side of Sentinel type, returning the number of steps from the
607/// sentinel to the iterator (which is non-positive).
608///
609/// This delegates work to `distance_from_sentinel`.
610template <class Iterator_t>
611 requires std::derived_from<Iterator_t, Iterator_interface<Iterator_t>> &&
612 requires { Iterator_t().distance_from_sentinel(); }
613[[nodiscard]] std::ptrdiff_t operator-(const Iterator_t &iterator,
614 const Default_sentinel &) {
615 return iterator.distance_from_sentinel();
616}
617
618/// Subtraction operator with the left-hand-side of Sentinel type and the
619/// right-hand-side of Iterator type, returning the number of steps from the
620/// iterator to the sentinel (which is non-negative).
621///
622/// This delegates work to `distance_from_sentinel()`.
623template <class Iterator_t>
624 requires std::derived_from<Iterator_t, Iterator_interface<Iterator_t>> &&
625 requires { Iterator_t().distance_from_sentinel(); }
626[[nodiscard]] std::ptrdiff_t operator-(const Default_sentinel &,
627 const Iterator_t &iterator) {
628 return -iterator.distance_from_sentinel();
629}
630
631/// Three-way comparison operator which compares two Iterator objects and
632/// returns a std::strong_ordering object.
633///
634/// This delegates work to `distance_from`.
635template <class Iterator_t>
636 requires std::derived_from<Iterator_t, Iterator_interface<Iterator_t>> &&
637 detail::Has_member_distance_from<Iterator_t>
638[[nodiscard]] std::strong_ordering operator<=>(const Iterator_t &it1,
639 const Iterator_t &it2) {
640 return it1.distance_from(it2) <=> 0;
641}
642
643/// Three-way comparison operator which compares an Iterator object and a
644/// Sentinel object and returns a std::strong_ordering object.
645///
646/// This delegates work to `distance_from_sentinel()`.
647template <class Iterator_t>
648 requires std::derived_from<Iterator_t, Iterator_interface<Iterator_t>> &&
649 detail::Has_member_distance_from_sentinel<Iterator_t>
650[[nodiscard]] std::strong_ordering operator<=>(const Iterator_t &it1,
651 const Default_sentinel &) {
652 return it1.distance_from_sentinel() <=> 0;
653}
654
655} // namespace mysql::iterators
656
657// ==== Specialization of iterator_traits ====
658
659/// Helper type to declare that an iterator is not a legacy iterator.
661
662/// Specialization of the standard library customization point
663/// std::iterator_traits, to subclasses of Iterator_interface.
664///
665/// This deduces the iterator category and defines other type members required
666/// for iterators to satisfy the standard library requirements for iterators.
667/// See also the "Specializations" section at
668/// https://en.cppreference.com/w/cpp/iterator/iterator_traits
669template <class Iterator_t>
670 requires std::derived_from<
673// The C++ standard explicitly allows specialization of `std::iterator_traits`,
674// but clang-tidy complains about extending `std`. Suppress that check.
675//
676// NOLINTNEXTLINE(cert-dcl58-cpp)
677struct std::iterator_traits<Iterator_t> {
678 using reference = decltype(*std::declval<Iterator_t>());
679 using pointer = decltype(std::declval<Iterator_t>().operator->());
680 using value_type = std::remove_cvref_t<reference>;
681 using difference_type = std::ptrdiff_t;
682
683 // Classes deriving from Iterator_interface must provide at least members
684 // that make it satisfy the `std::input_iterator` concept.
686
687 // Deduce the iterator category based on the existence of members. To define
688 // the type using compile-time conditions, we take the decltype of the return
689 // type of a lambda function, whose body consists of `if constexpr`
690 // expressions that decide what type the lambda function returns.
691
692 /// @cond DOXYGEN_DOES_NOT_UNDERSTAND_THIS
693 using iterator_category = decltype([] {
695 Iterator_t>)
696 return std::contiguous_iterator_tag{};
698 Iterator_t>)
699 return std::random_access_iterator_tag{};
701 Iterator_t>)
702 return std::bidirectional_iterator_tag{};
704 Iterator_t>)
705 return std::forward_iterator_tag{};
707 Iterator_t>)
708 return std::input_iterator_tag{};
709 else
710 return Not_a_legacy_iterator{};
711 }());
712 /// @endcond
713
714 // Deduce the iterator concept.
715 //
716 // Note that "each concept is not satisfied if the required operations are not
717 // supported, regardless of the tag", according to
718 // https://en.cppreference.com/w/cpp/iterator/iterator_tags. In other words,
719 // the actual iterator concepts satisfied may be weaker than the tag we
720 // specify here.
721 using iterator_concept = decltype([] {
722 // For the weaker iterator concepts `std::input_iterator`,
723 // `std::forward_iterator`, `std::bidirectional_iterator`, and
724 // `std::random_access_iterator`, we may use either
725 // `contiguous_iterator_tag` or `random_access_iterator_tag`. Concepts such
726 // as `std::bidirectional_iterator` hold if *both* the tag derives from
727 // bidirectional_iterator_tag *and* the class meets syntactic requirements;
728 // thus it is ok for this declaration to use a tag that refers to a too
729 // strong iterator conept.
730 //
731 // However, the syntactic requirements for `std::contiguous_iterator` may be
732 // satisfied also for `random_access_iterators` (even if they do not model
733 // all the semantic requirements of `contiguous_iterator`). Therefore we
734 // distingiush them by the existence of `get_pointer()` in the
735 // implementation.
737 Iterator_t>) {
738 return std::contiguous_iterator_tag{};
739 } else {
740 return std::random_access_iterator_tag{};
741 }
742 }());
743}; // struct std::iterator_traits<Iterator_t>
744
745/// Specialization of the standard library customization point
746/// std::pointer_traits, to subclasses of Iterator_interface which declare
747/// themselves to be contiguous iterators.
748template <class Iterator_t>
749 requires std::derived_from<
752// The C++ standard explicitly allows specialization of `std::pointer_traits`,
753// but clang-tidy complains about extending `std`. Suppress that check.
754//
755// NOLINTNEXTLINE(cert-dcl58-cpp)
756struct std::pointer_traits<Iterator_t> {
757 using pointer = decltype(std::declval<Iterator_t>().operator->());
758 using element_type = decltype(std::declval<Iterator_t>().operator*());
759 using difference_type = std::ptrdiff_t;
760 template <class Other>
761 using rebind = Other *;
762 static pointer pointer_to(element_type &r) { return &r; }
763}; // struct std::pointer_traits<Iterator_t>
764
765/// Specialization of the standard library customization points
766/// std::indirectly_readable_traits and std::incrementable_traits. This is
767/// needed for iterators that satisfy the input iterator concept but not input
768/// iterator category (as they don't have a specialization of iterator_traits).
769//
770// The recommended way to do this is to use a syntax that specifies the `std`
771// namespace as a name qualifier, like `struct std::hash<Gtid_t>`, rather than
772// enclose the entire struct in a namespace block.
773//
774// However, gcc 11.4.0 on ARM has a bug that makes it produce "error:
775// redefinition of 'struct std::indirectly_readable_traits<_Iter>'" when using
776// that syntax. See https://godbolt.org/z/Yd13x8M56 vs
777// https://godbolt.org/z/Ys8hqbevs .
778//
779// Todo: Switch to the recommended syntax once we drop support for compilers
780// having this bug.
781namespace std {
782template <class Iterator_t>
783 requires std::derived_from<Iterator_t,
785// The C++ standard explicitly allows specialization of
786// `std::indirectly_readable_traits`, but clang-tidy complains about extending
787// `std`. Suppress that check.
788//
789// NOLINTNEXTLINE(cert-dcl58-cpp)
790struct indirectly_readable_traits<Iterator_t> {
791 using value_type = std::remove_cvref_t<decltype(*std::declval<Iterator_t>())>;
792};
793
794template <class Iterator_t>
795 requires std::derived_from<Iterator_t,
797// The C++ standard explicitly allows specialization of
798// `std::incrementable_traits`, but clang-tidy complains about extending `std`.
799// Suppress that check.
800//
801// NOLINTNEXTLINE(cert-dcl58-cpp)
802struct incrementable_traits<Iterator_t> {
803 using difference_type = std::ptrdiff_t;
804};
805
806} // namespace std
807
808// addtogroup GroupLibsMysqlIterators
809/// @}
810
811#endif // ifndef MYSQL_ITERATORS_ITERATOR_INTERFACE_H
Used like std::default_sentinel_t / std::default_sentinel.
Definition: iterator_interface.h:212
auto operator<=>(const Default_sentinel &) const =default
bool operator==(const Default_sentinel &) const =default
CRTP base class (mixin) that makes your class a standard-compliant iterator, given only a minimal set...
Definition: iterator_interface.h:370
auto operator++(int)
Post-increment operator, which advances the position one step.
Definition: iterator_interface.h:431
Self_t operator-(std::ptrdiff_t delta) const
Subtraction-of-integer operator, which returns a new iterator that is the given number of steps behin...
Definition: iterator_interface.h:521
auto operator->() const
Arrow operator, return a pointer (possibly a fancy pointer) to the current element.
Definition: iterator_interface.h:397
Self_t & operator++()
Pre-increment operator, which advances the position one step and returns a reference to the iterator ...
Definition: iterator_interface.h:416
Self_tp Self_t
Definition: iterator_interface.h:372
std::ptrdiff_t operator-(const Self_t &other) const
Subtraction-of-iterator operator, which returns the number of steps from other this.
Definition: iterator_interface.h:531
Self_t & operator--()
Pre-decrement iterator, which moves one step back and returns a reference to the iterator itself.
Definition: iterator_interface.h:450
auto operator--(int)
Post-decrement operator, which moves one step back and returns a copy of the iterator before the decr...
Definition: iterator_interface.h:467
Self_t & operator-=(std::ptrdiff_t delta)
Subtraction assignment operator, which moves the iterator backward by the given number of steps,...
Definition: iterator_interface.h:499
Self_t & operator+=(std::ptrdiff_t delta)
Addition assignment operator, which moves the iterator forward by the given number of steps,...
Definition: iterator_interface.h:488
Self_t operator+(std::ptrdiff_t delta) const
Addition operator, which returns a new iterator that is the given number of steps ahead of the curren...
Definition: iterator_interface.h:509
Auxiliary object that holds a value internally, and operator-> returns a pointer to the value.
Definition: iterator_interface.h:182
Value_t m_value
Definition: iterator_interface.h:195
Value_t * operator->()
Definition: iterator_interface.h:192
Value_tp Value_t
Definition: iterator_interface.h:184
Dereferenceable_wrapper(Args_t &&...args)
Definition: iterator_interface.h:189
True if Type has the members required for Iterator_interface<Type> to satisfy std::input_iterator.
Definition: iterator_interface.h:129
true if Type has the members required for Iterator_interface<Type> to meet the syntactic requirements...
Definition: iterator_interface.h:152
true if Type has the members required for Iterator_interface<Type> to meet the syntactic requirements...
Definition: iterator_interface.h:166
True if Type has the members and the value type for required for Iterator_interface<Type> to meet the...
Definition: iterator_interface.h:143
True if Type has the members required for Iterator_interface<Type> to meet the syntactic requirements...
Definition: iterator_interface.h:136
true if Type has the members required for Iterator_interface<Type> to meet the syntactic requirements...
Definition: iterator_interface.h:159
true if Type has an is_equal or distance_from member.
Definition: iterator_interface.h:116
true if Type has an advance member
Definition: iterator_interface.h:97
true if Type has a distance_from member
Definition: iterator_interface.h:109
true if Type has a distance_from member
Definition: iterator_interface.h:102
Helper: returns true if Type has a get function, regardless if it returns void or not.
Definition: iterator_interface.h:49
true if Type has a get member that returns a pointer.
Definition: iterator_interface.h:65
true if Type has a get member that returns a reference type.
Definition: iterator_interface.h:72
Helper: returns true if Type has a get function that returns void (which does not make it an iterator...
Definition: iterator_interface.h:54
true if Type has a get member that does not return void.
Definition: iterator_interface.h:60
true if Type has an is_equal member.
Definition: iterator_interface.h:81
true if Type has an is_sentinel member.
Definition: iterator_interface.h:87
true if Type has a next member.
Definition: iterator_interface.h:77
true if Type has a prev member
Definition: iterator_interface.h:93
Definition: is_pointer.h:40
false if Args is exactly one type, say A, and std::decay_t<A> equals Type.
Definition: not_decayed.h:84
Experimental API header.
MediaType
Definition: media_type.h:33
Definition: iterator_interface.h:39
Definition: empty_sequence_iterator.h:37
Iterator_t operator+(std::ptrdiff_t delta, const Iterator_t &iterator)
Addition operator with the left-hand-side of type ptrdiff_t and the right-hand-side of Iterator type,...
Definition: iterator_interface.h:600
bool operator==(const Iterator_t &a, const Iterator_t &b)
Equality operator, which returns true if the two iterators are equal.
Definition: iterator_interface.h:566
constexpr Default_sentinel default_sentinel
Definition: iterator_interface.h:217
std::ptrdiff_t operator-(const Iterator_t &iterator, const Default_sentinel &)
Subtraction operator with the left-hand-side of Iterator type and the right-hand-side of Sentinel typ...
Definition: iterator_interface.h:613
std::strong_ordering operator<=>(const Iterator_t &it1, const Iterator_t &it2)
Three-way comparison operator which compares two Iterator objects and returns a std::strong_ordering ...
Definition: iterator_interface.h:638
static mysql_service_status_t get(THD **thd) noexcept
Definition: mysql_current_thread_reader_all_empty.cc:31
Define std::hash<Gtid>.
Definition: gtid.h:355
Experimental API header.
const mysql_service_registry_t * r
Definition: pfs_example_plugin_employee.cc:86
Helper type to declare that an iterator is not a legacy iterator.
Definition: iterator_interface.h:660
std::ptrdiff_t difference_type
Definition: iterator_interface.h:803
std::remove_cvref_t< decltype(*std::declval< Iterator_t >())> value_type
Definition: iterator_interface.h:791
std::remove_cvref_t< reference > value_type
Definition: iterator_interface.h:680
decltype(std::declval< Iterator_t >().operator->()) pointer
Definition: iterator_interface.h:679
decltype([] { if constexpr(mysql::iterators::detail::Has_member_get_pointer< Iterator_t >) { return std::contiguous_iterator_tag{} iterator_concept
Definition: iterator_interface.h:738
decltype(*std::declval< Iterator_t >()) reference
Definition: iterator_interface.h:678
std::ptrdiff_t difference_type
Definition: iterator_interface.h:681
static pointer pointer_to(element_type &r)
Definition: iterator_interface.h:762
decltype(std::declval< Iterator_t >().operator*()) element_type
Definition: iterator_interface.h:758
std::ptrdiff_t difference_type
Definition: iterator_interface.h:759
Other * rebind
Definition: iterator_interface.h:761
decltype(std::declval< Iterator_t >().operator->()) pointer
Definition: iterator_interface.h:757