basic_match_range#

Synopsis#

The lazy range find_iter() returns. Iterate it with a range-for; each element is a match result. Nothing is scanned until the iterator advances, and each step applies the non-overlapping and empty-match advance rules.

Interface#

The range is what find_iter returns. Constructing one from a program_view is the engine’s job; user code only iterates.

template<typename Storage, bool TrailingLA = false>
class basic_match_range#

A range of matches, returned by find_iter() and usable in range-for.

The regex and the text must outlive the range. Empty matches follow Python: an empty match is yielded, then the scan advances one codepoint.

Template Parameters:

Storage – The regex’s storage policy.

Public Functions

inline constexpr basic_match_iterator<Storage, TrailingLA> begin() const#

Returns an iterator to the first match.

Returns:

An iterator positioned on the first match, or equal to end when there is none.

inline constexpr basic_match_iterator<Storage, TrailingLA> end() const#

Returns the end sentinel.

Returns:

The past-the-end iterator.

template<typename Storage, bool TrailingLA = false>
class basic_match_iterator#

Forward iterator over the non-overlapping matches in a text.

Follows Python’s empty-match rules: an empty match is yielded (even right after a non-empty one), then the scan advances by one codepoint. The regex and the text must outlive the iterator. Obtained from basic_match_range.

Template Parameters:

Storage – The regex’s storage policy (selects the result/scratch types).

Public Types

using value_type = basic_match_result<typename Storage::slot_storage>#

Yielded match type.

Public Functions

constexpr basic_match_iterator() = default#

Constructs the end sentinel.

inline constexpr const value_type &operator*() const#

Returns the current match.

Returns:

A reference to the result, valid until the next increment.

inline constexpr const value_type *operator->() const#

Returns pointer to the current match.

Returns:

A pointer to the result, valid until the next increment.

inline constexpr basic_match_iterator &operator++()#

Advances to the next match.

Returns:

*this.

inline constexpr basic_match_iterator operator++(int)#

Advances to the next match (post-increment).

Returns:

A copy of the iterator at its pre-increment position.

inline constexpr bool exhausted() const noexcept#

Whether the walk is over, without building an end sentinel to compare against.

Prefer this in a hand-rolled loop: it == basic_match_iterator{} answers the same question, but a default-constructed iterator is a full walker and is expensive to materialise just to test.

Returns:

true once no further match will be produced.

inline constexpr bool operator==(const basic_match_iterator &other) const#

Returns true if both denote the same position/end.

Parameters:

other[in] Another iterator.

Returns:

true if both denote the same position/end.

Complexity#

Lazy: each increment advances to the next match. A full traversal is one guaranteed linear scan of the text – O(len(text)) – and never backtracks (ReDoS-safe by construction). Prefer exhausted() over comparing against a default-constructed end iterator in a hand-rolled loop.

Example#

Compiled and run by the example-check gate on every push – empty-match advance and a region (pos is a start offset, not a slice):

  // Empty-match rule (Python): yield the empty match, then advance one codepoint.
  const real::regex maybe {R"(a*)"};
  std::size_t empties = 0;
  for (const auto& hit : maybe.find_iter("bb")) {
    if (hit.start() == hit.end()) {
      ++empties;
    }
  }
  // "bb" has three cursor positions, including the end: [0,0) [1,1) [2,2).

  // pos is a start offset, not a slice -- iteration begins at byte 4.
  const real::regex word {R"(\w+)"};
  constexpr auto phrase = "one two three"sv;
  for (const auto& hit : word.find_iter(phrase, 4)) {
    std::cout << hit[0] << "\n";  // two, then three
  }

See also#