std::regex compatibility#

Synopsis#

real::compat – the <regex> API you already type, on the linear engine: basic_regex (aliases regex / wregex), the regex_match / regex_search / regex_replace families, match_results (aliases smatch / cmatch) and the two iterators. Which patterns run on REAL and which fall back is the compatibility contract; migration lives in the std::regex drop-in – this page is the object reference.

Interface#

template<typename CharT = char, typename Traits = std::regex_traits<CharT>>
class basic_regex#

A std::basic_regex-compatible pattern, backed by REAL where it can serve the pattern, else by std.

Template Parameters:
  • CharT – Character type (char; other types route straight to std).

  • Traits – Regex traits (std parity).

Public Functions

basic_regex() = default#

An empty pattern on the std backend — the variant’s first alternative default-constructs.

inline explicit basic_regex(const CharT *pattern, flag_type f = regex_constants::ECMAScript, policy pol = policy::strict)#

Compiles pattern from a C string.

Parameters:
  • pattern – [in] NUL-terminated pattern text.

  • f – [in] Syntax options; the grammar they select may route the pattern to std.

  • pol – [in] Strict rejects a pattern REAL cannot represent linearly; fallback routes it to std.

Throws:

real::compat::regex_error – on an invalid pattern, or on a strict-policy rejection.

inline explicit basic_regex(const string_type &pattern, flag_type f = regex_constants::ECMAScript, policy pol = policy::strict)#

Compiles pattern from an owned string.

Parameters:
  • pattern – [in] The pattern text.

  • f – [in] Syntax options.

  • pol – [in] Rejection policy; see the C-string overload.

Throws:

real::compat::regex_error – on an invalid pattern, or on a strict-policy rejection.

inline basic_regex(const CharT *pattern, std::size_t len, flag_type f = regex_constants::ECMAScript, policy pol = policy::strict)#

Compiles the first len characters of pattern, which need not be NUL-terminated.

Parameters:
  • pattern – [in] Pattern text.

  • len – [in] Its length in characters.

  • f – [in] Syntax options.

  • pol – [in] Rejection policy.

Throws:

real::compat::regex_error – on an invalid pattern, or on a strict-policy rejection.

template<typename It>
inline basic_regex(It begin, It end, flag_type f = regex_constants::ECMAScript, policy pol = policy::strict)#

Compiles the pattern in [begin, end).

Parameters:
  • begin – [in] Start of the pattern text.

  • end – [in] One past its end.

  • f – [in] Syntax options.

  • pol – [in] Rejection policy.

Throws:

real::compat::regex_error – on an invalid pattern, or on a strict-policy rejection.

inline basic_regex(std::initializer_list<CharT> pattern, flag_type f = regex_constants::ECMAScript, policy pol = policy::strict)#

Compiles the characters of pattern.

Parameters:
  • pattern – [in] The pattern text.

  • f – [in] Syntax options.

  • pol – [in] Rejection policy.

Throws:

real::compat::regex_error – on an invalid pattern, or on a strict-policy rejection.

inline basic_regex &operator=(const CharT *pattern)#

Replaces the pattern with pattern, as assign(pattern).

Parameters:

pattern – [in] NUL-terminated pattern text.

Throws:

real::compat::regex_error – as assign does; *this is then unchanged.

Returns:

*this.

inline basic_regex &operator=(std::initializer_list<CharT> pattern)#

Replaces the pattern with pattern, as assign(pattern).

Parameters:

pattern – [in] The pattern text.

Throws:

real::compat::regex_error – as assign does; *this is then unchanged.

Returns:

*this.

template<typename ST, typename SA>
inline basic_regex &operator=(const std::basic_string<CharT, ST, SA> &pattern)#

Replaces the pattern with pattern, as assign(pattern).

Template Parameters:
  • ST – The string’s traits.

  • SA – The string’s allocator.

Parameters:

pattern – [in] The pattern text.

Throws:

real::compat::regex_error – as assign does; *this is then unchanged.

Returns:

*this.

inline basic_regex &assign(const basic_regex &other)#

Becomes a copy of other.

Parameters:

other – [in] The regex to copy.

Returns:

*this.

inline basic_regex &assign(basic_regex &&other) noexcept#

Takes other's pattern.

Parameters:

other – [inout] The regex to move from.

Returns:

*this.

inline basic_regex &assign(const CharT *pattern, flag_type f = regex_constants::ECMAScript)#

Compiles pattern in place of the current one, under this regex’s policy. Every overload gives the strong guarantee std’s does: on a throw *this is unchanged.

Parameters:
  • pattern – [in] NUL-terminated pattern text.

  • f – [in] Syntax options.

Throws:

real::compat::regex_error – on an invalid pattern, or on a strict-policy rejection.

Returns:

*this.

inline basic_regex &assign(const CharT *pattern, std::size_t len, flag_type f = regex_constants::ECMAScript)#

Compiles the first len characters of pattern in place of the current pattern.

Parameters:
  • pattern – [in] Pattern text.

  • len – [in] Its length in characters.

  • f – [in] Syntax options.

Throws:

real::compat::regex_error – as the C-string overload does; *this is then unchanged.

Returns:

*this.

template<typename ST, typename SA>
inline basic_regex &assign(const std::basic_string<CharT, ST, SA> &pattern, flag_type f = regex_constants::ECMAScript)#

Compiles pattern in place of the current pattern.

Template Parameters:
  • ST – The string’s traits.

  • SA – The string’s allocator.

Parameters:
  • pattern – [in] The pattern text.

  • f – [in] Syntax options.

Throws:

real::compat::regex_error – as the C-string overload does; *this is then unchanged.

Returns:

*this.

template<typename InputIt>
inline basic_regex &assign(InputIt first, InputIt last, flag_type f = regex_constants::ECMAScript)#

Compiles the pattern in [first, last) in place of the current pattern.

Template Parameters:

InputIt – An input iterator over characters.

Parameters:
  • first – [in] Start of the pattern text.

  • last – [in] One past its end.

  • f – [in] Syntax options.

Throws:

real::compat::regex_error – as the C-string overload does; *this is then unchanged.

Returns:

*this.

inline basic_regex &assign(std::initializer_list<CharT> pattern, flag_type f = regex_constants::ECMAScript)#

Compiles the characters of pattern in place of the current pattern.

Parameters:
  • pattern – [in] The pattern text.

  • f – [in] Syntax options.

Throws:

real::compat::regex_error – as the C-string overload does; *this is then unchanged.

Returns:

*this.

inline std::size_t mark_count() const noexcept#

Number of marked sub-expressions (excluding group 0), as std::basic_regex.

Returns:

The group count.

inline flag_type flags() const noexcept#

The flags this regex was built with.

Returns:

Those flags.

inline void swap(basic_regex &other) noexcept#

Exchanges engines, flags, policy and cached state with other.

Parameters:

other – [inout] The regex to swap with.

inline bool uses_real() const noexcept#

True if this regex is backed by the real engine (vs the std fallback).

Returns:

true if REAL’s linear engine holds it.

inline compat::policy policy() const noexcept#

The drop-in policy this regex was constructed with.

Returns:

Strict or fallback.

inline bool nullable() const noexcept#

Whether the pattern can match the empty string; under a POSIX grammar a nullable pattern’s replace and iteration run on std (uses_real_traversal).

Returns:

true if it is nullable.

inline bool uses_real_traversal() const noexcept#

Whether replace and iteration run on REAL: real-backed, not a nullable POSIX pattern (std’s leftmost-longest empty-match traversal is not modelled), and no capturing group nullable under a quantifier ((ab|)+a): REAL captures its last consuming iteration, libstdc++ and libc++ an extra empty one. Search and match keep that one capture divergence, by design (docs/COMPATIBILITY.md).

Returns:

true for a real-backed pattern whose traversal real models.

template<typename BidirIt, typename Alloc = std::allocator<sub_match<BidirIt>>>
class match_results#

The result of a match: group sub-matches plus the prefix and suffix.

Holds both ends of the searched sequence: the suffix’s end is not derivable from a base iterator. Filled from REAL’s byte offsets, or copied from a std::match_results on the std path.

Template Parameters:
  • BidirIt – A bidirectional iterator into the searched sequence.

  • Alloc – Allocator for the sub-match vector.

Public Functions

inline bool ready() const noexcept#

Whether a successful match has been stored.

Returns:

true once a search or match has filled this object.

inline size_type size() const noexcept#

Number of marks (groups), including group 0; 0 when there was no match.

Returns:

The sub-match count.

inline bool empty() const noexcept#

Whether there are no marks at all.

Returns:

true when size is 0, i.e. no match was stored.

inline const_reference operator[](size_type n) const#

The sub-match for group n. An out-of-range n yields an unmatched sub-match anchored at the sequence end, as libstdc++ and libc++ do; a token iterator’s out-of-range selector relies on it.

Parameters:

n – [in] Group index; 0 is the whole match.

Returns:

That group’s sub-match, or the end-anchored unmatched one when n is out of range.

inline difference_type position(size_type n = 0) const#

Start offset of group n; an out-of-range group sits at the end, as in std.

Parameters:

n – [in] Group index; 0 is the whole match.

Returns:

Its start offset from the sequence start.

inline difference_type length(size_type n = 0) const#

Length of group n (0 if out of range or unmatched).

Parameters:

n – [in] Group index; 0 is the whole match.

Returns:

Its length in characters.

inline string_type str(size_type n = 0) const#

Matched text of group n (empty if out of range or unmatched).

Parameters:

n – [in] Group index; 0 is the whole match.

Returns:

An owned copy of its text.

inline const value_type &prefix() const#

The unmatched prefix (sequence start up to the whole match).

Returns:

The prefix sub-match; see rebase_prefix for what it means during iteration.

inline const value_type &suffix() const#

The unmatched suffix (whole match end to sequence end).

Returns:

The suffix sub-match.

inline const_iterator begin() const#

Iteration over the marks, group 0 first.

Returns:

A const iterator to the first sub-match, as in std::match_results.

inline const_iterator end() const#

End of the mark range.

Returns:

One past the last sub-match.

inline void swap(match_results &other) noexcept#

Exchanges the whole state with other.

Parameters:

other – [inout] The result to swap with.

template<typename OutputIter>
inline OutputIter format(OutputIter out, const char_type *fmt_first, const char_type *fmt_last, regex_constants::match_flag_type flags = regex_constants::format_default) const#

Writes [fmt_first, fmt_last) with its references replaced by this match’s text (std::match_results::format).

ECMAScript rules: a dollar followed by a dollar, an ampersand, a backtick, a quote or one or two digits inserts a dollar, the match, the prefix, the suffix or that group (nothing for a group that does not exist); any other dollar is itself. $0 reads as the native std reads it. format_sed selects sed’s.

Template Parameters:

OutputIter – An output iterator over characters.

Parameters:
  • out – [out] Where the result is written.

  • fmt_first – [in] Start of the format.

  • fmt_last – [in] One past its end.

  • flags – [in] format_sed selects sed’s rules; the other bits are ignored.

Returns:

out advanced past what was written.

Pre:

ready()

template<typename OutputIter, typename ST, typename SA>
inline OutputIter format(OutputIter out, const std::basic_string<char_type, ST, SA> &fmt, regex_constants::match_flag_type flags = regex_constants::format_default) const#

format over a string format.

Template Parameters:
  • OutputIter – An output iterator over characters.

  • ST – The format’s traits.

  • SA – The format’s allocator.

Parameters:
  • out – [out] Where the result is written.

  • fmt – [in] The format.

  • flags – [in] format_sed selects sed’s rules.

Returns:

out advanced past what was written.

Pre:

ready()

template<typename ST, typename SA>
inline std::basic_string<char_type, ST, SA> format(const std::basic_string<char_type, ST, SA> &fmt, regex_constants::match_flag_type flags = regex_constants::format_default) const#

format into a new string.

Template Parameters:
  • ST – The format’s traits.

  • SA – The format’s allocator.

Parameters:
  • fmt – [in] The format.

  • flags – [in] format_sed selects sed’s rules.

Returns:

The expanded format.

Pre:

ready()

inline string_type format(const char_type *fmt, regex_constants::match_flag_type flags = regex_constants::format_default) const#

format of a C-string format into a new string.

Parameters:
  • fmt – [in] The NUL-terminated format.

  • flags – [in] format_sed selects sed’s rules.

Returns:

The expanded format.

Pre:

ready()

template<typename BidirIt>
class sub_match#

A matched sub-expression: a [first, second) range into the searched sequence. Any bidirectional iterator, as std::sub_match; only view needs contiguous storage.

Template Parameters:

BidirIt – A bidirectional iterator into the searched sequence.

Public Functions

inline difference_type length() const#

Length of the sub-match (0 if it did not participate).

Returns:

second - first, or 0 when matched is false.

inline string_type str() const#

The matched text as an owned string (empty if it did not participate).

Returns:

A copy of [first, second), or an empty string when matched is false.

inline int compare(const string_type &other) const#

Three-way length/lexicographic comparison against a string (std::sub_match::compare).

Parameters:

other – [in] The string to compare against.

Returns:

Negative, zero or positive as str() orders before, equal to, or after other.

inline int compare(const value_type *other) const#

Three-way comparison against a C string (std::sub_match::compare).

Parameters:

other – [in] The NUL-terminated string to compare against.

Returns:

Negative, zero or positive as str() orders before, equal to, or after other.

inline int compare(const sub_match &other) const#

Three-way comparison against another sub-match, by matched text.

Parameters:

other – [in] The sub-match to compare against.

Returns:

Negative, zero or positive as str() orders before, equal to, or after other.str().

Public Members

BidirIt first = {}#

Start of the sub-match.

BidirIt second = {}#

One past the end of the sub-match.

bool matched = {false}#

Whether this sub-expression participated.

class regex_error : public std::regex_error#

std::regex_error-compatible exception; every regex error this layer reports has this type.

  • A syntax error: std’s own code() and what().

  • A strict-policy rejection (policy) of a pattern std accepts but REAL cannot run linearly: error_complexity, with a message naming REAL.

  • An error the std backend raises while matching (error_complexity, error_stack): std’s code.

Public Functions

inline explicit regex_error(const std::regex_error &error)#

From a std error, keeping its code and message.

Parameters:

error – [in] The standard library error to adopt.

inline explicit regex_error(std::regex_constants::error_type code)#

With a code alone, as std::regex_error(code); the message is std’s for that code.

Parameters:

code – [in] The error category.

inline regex_error(std::regex_constants::error_type code, std::string message)#

With an explicit code and message — the strict-policy rejection of a pattern REAL cannot represent linearly (error_complexity), carrying a REAL-identifiable message.

Parameters:
  • code – [in] The std::regex_constants::error_type to report.

  • message – [in] The text what returns.

inline const char *what() const noexcept override#

The message, which for a strict-policy rejection identifies REAL as the source.

Returns:

A NUL-terminated message valid for this object’s lifetime.

template<typename BidirIt, typename CharT = typename std::iterator_traits<BidirIt>::value_type, typename Traits = std::regex_traits<CharT>>
class regex_iterator#

Iterates the non-overlapping matches of a pattern in a sequence (std::regex_iterator).

REAL drives the traversal when basic_regex::uses_real_traversal holds and detail::real_honors accepts the flags; otherwise this wraps a std::regex_iterator. Default-constructed, it is the end sentinel.

Template Parameters:

BidirIt – A bidirectional iterator into the searched sequence.

Public Functions

regex_iterator() = default#

Constructs the end sentinel.

inline regex_iterator(BidirIt first, BidirIt last, const regex_type &re, regex_constants::match_flag_type flags = regex_constants::match_default)#

Constructs a begin iterator over [first, last) and finds the first match.

Parameters:
  • first – [in] Start of the character sequence.

  • last – [in] End of the character sequence.

  • re – [in] The pattern; it must outlive this iterator.

  • flags – [in] Match flags; a constraining one routes the iteration to std.

inline regex_iterator(const regex_iterator &other)#

Copies the iteration position but not the walker (an accelerator over real_pos_). Cloning its VM scratch, or sharing it copy-on-write, would cost every it++; a copy builds its own walker only if it advances.

Parameters:

other – [in] The iterator to copy.

regex_iterator(regex_iterator&&) noexcept = default#

Moves the walker along with the position.

regex_iterator(BidirIt first, BidirIt last, const regex_type &&re, regex_constants::match_flag_type flags = regex_constants::match_default) = delete#

Constructing from a temporary regex would dangle (std::regex_iterator parity).

inline reference operator*() const#

The current match.

Returns:

A reference to it, valid until the next increment.

inline regex_iterator &operator++()#

Advances to the next match, becoming the end sentinel when there is none.

Returns:

*this.

inline regex_iterator operator++(int)#

Advances to the next match, returning the previous position.

Returns:

A copy of *this as it was before the increment.

inline bool operator==(const regex_iterator &other) const#

Equality. Two non-end iterators compare equal only for the same regex, sequence, flags and current match — not for a coincidental same position across different patterns.

Parameters:

other – [in] The iterator to compare against.

Returns:

Whether the two denote the same iteration position.

template<typename BidirIt, typename CharT = typename std::iterator_traits<BidirIt>::value_type, typename Traits = std::regex_traits<CharT>>
class regex_token_iterator#

Enumerates selected sub-matches, or the text between matches (std::regex_token_iterator).

Wraps regex_iterator, whose routing it inherits. Per match it yields the requested fields in order: N >= 0 is group N (unmatched when the group took no part), -1 the match’s prefix, the text since the previous match. As in std, a final -1 field yields the last suffix only if it is non-empty, while an empty field between adjacent matches is produced; with no match at all, -1 yields the whole sequence as one token.

Template Parameters:

BidirIt – A bidirectional iterator into the searched sequence.

Public Functions

regex_token_iterator() = default#

Constructs the end sentinel.

inline regex_token_iterator(BidirIt first, BidirIt last, const regex_type &re, int submatch = 0, regex_constants::match_flag_type flags = regex_constants::match_default)#

Selects a single sub-match field (0 = whole match, N = group N, -1 = split).

Parameters:
  • first – [in] Start of the character sequence.

  • last – [in] End of the character sequence.

  • re – [in] The pattern; it must outlive this iterator.

  • submatch – [in] The field to yield per match.

  • flags – [in] Match flags, defaulting to regex_constants::match_default.

inline regex_token_iterator(BidirIt first, BidirIt last, const regex_type &re, const std::vector<int> &submatches, regex_constants::match_flag_type flags = regex_constants::match_default)#

Selects a list of fields, cycled per match (e.g. {1, 2}, {-1}).

Parameters:
  • first – [in] Start of the character sequence.

  • last – [in] End of the character sequence.

  • re – [in] The pattern; it must outlive this iterator.

  • submatches – [in] The fields to cycle through; an empty list is treated as {0}.

  • flags – [in] Match flags, defaulting to regex_constants::match_default.

inline regex_token_iterator(BidirIt first, BidirIt last, const regex_type &re, std::initializer_list<int> submatches, regex_constants::match_flag_type flags = regex_constants::match_default)#

Selects a list of fields from a braced list (e.g. {-1}).

Parameters:
  • first – [in] Start of the character sequence.

  • last – [in] End of the character sequence.

  • re – [in] The pattern; it must outlive this iterator.

  • submatches – [in] The fields to cycle through.

  • flags – [in] Match flags, defaulting to regex_constants::match_default.

template<std::size_t N>
inline regex_token_iterator(BidirIt first, BidirIt last, const regex_type &re, const int (&submatches)[N], regex_constants::match_flag_type flags = regex_constants::match_default)#

Selects the fields of a C array (e.g. const int fields[] {1, 2}).

Template Parameters:

N – The number of fields.

Parameters:
  • first – [in] Start of the character sequence.

  • last – [in] End of the character sequence.

  • re – [in] The pattern; it must outlive this iterator.

  • submatches – [in] The fields to cycle through.

  • flags – [in] Match flags, defaulting to regex_constants::match_default.

regex_token_iterator(BidirIt first, BidirIt last, const regex_type &&re, int submatch = 0, regex_constants::match_flag_type flags = regex_constants::match_default) = delete#

Constructing from a temporary regex would dangle (std::regex_token_iterator parity).

regex_token_iterator(BidirIt first, BidirIt last, const regex_type &&re, const std::vector<int> &submatches, regex_constants::match_flag_type flags = regex_constants::match_default) = delete#

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

regex_token_iterator(BidirIt first, BidirIt last, const regex_type &&re, std::initializer_list<int> submatches, regex_constants::match_flag_type flags = regex_constants::match_default) = delete#

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

template<std::size_t N>
regex_token_iterator(BidirIt first, BidirIt last, const regex_type &&re, const int (&submatches)[N], regex_constants::match_flag_type flags = regex_constants::match_default) = delete#

This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.

inline reference operator*() const#

The current token.

Returns:

A reference to it, valid until the next increment.

inline regex_token_iterator &operator++()#

Advances to the next token, becoming the end sentinel when the fields are exhausted.

Returns:

*this.

inline regex_token_iterator operator++(int)#

Advances to the next token, returning the previous position.

Returns:

A copy of *this as it was before the increment.

inline bool operator==(const regex_token_iterator &other) const#

Equality. Two non-end iterators compare equal only for the same underlying walk, field selectors, field index, suffix state and current token.

Parameters:

other – [in] The iterator to compare against.

Returns:

Whether the two denote the same iteration position.

Matching and replacing#

The <regex> free functions ship with their full standard overload sets (C strings, std::string, iterator pairs, with or without a match_results):

  • regex_match – the whole range must match.

  • regex_search – leftmost match anywhere in the range.

  • regex_replace – template substitution over every match.

Their complete signatures render in the Doxygen namespace reference:

real::compat — every overload (/api).

Constants and policy#

The <regex> constants the constructors and free functions take, and the policy knob that picks strict rejection or the std::regex fallback:

enum real::compat::regex_constants::syntax_option_type#

Grammar / option flags (own bit values; mapped to real::flags or std at construction).

Values:

enumerator ECMAScript#

The default grammar.

enumerator icase#

Case-insensitive (ASCII).

enumerator nosubs#

Do not expose sub-expressions; std only, so rejected under policy::strict.

enumerator optimize#

Hint to favour matching speed; honoured as a no-op.

enumerator collate#

Locale-sensitive ranges; std only, so rejected under policy::strict.

enumerator multiline#

^/$ match at line boundaries.

enumerator basic#

POSIX BRE — translated onto REAL when the pattern translates, else the std backend.

enumerator extended#

POSIX ERE — translated onto REAL when the pattern translates, else the std backend.

enumerator awk#

awk grammar (ERE + C escapes) — translated onto REAL when it translates, else std.

enumerator grep#

grep grammar (BRE, lines joined by |) — translated onto REAL when it translates, else std.

enumerator egrep#

egrep grammar (ERE, lines joined by |) — translated onto REAL when it translates, else std.

enum real::compat::regex_constants::match_flag_type#

Match-control flags: the common subset.

Values:

enumerator match_default#

No constraint; the operation may stay on REAL.

enumerator match_not_bol#

^ does not match the start of the sequence.

enumerator match_not_eol#

$ does not match the end of the sequence.

enumerator match_not_bow#

\b does not match at the start.

enumerator match_not_eow#

\b does not match at the end.

enumerator match_any#

Any match will do; REAL satisfies it by returning the leftmost one.

enumerator match_not_null#

Do not match an empty sequence.

enumerator match_continuous#

The match must start at the first character.

enumerator match_prev_avail#

--first is valid, so ^ and \b may inspect the character before it.

enumerator format_default#

ECMAScript replacement syntax, copying the unmatched text.

enumerator format_sed#

sed’s replacement syntax: &, a backslash and a digit or character; $ is literal.

enumerator format_no_copy#

Do not copy the parts of the text that did not match.

enumerator format_first_only#

Replace only the first match.

enum class real::compat::policy : std::uint8_t#

The policy for a pattern the linear engine cannot represent (a backreference, an unbounded lookbehind, a POSIX class, …): strict, the default, rejects it; fallback delegates it to std::regex, forfeiting the linear-time guarantee for that pattern.

The guarantee covers the calls REAL runs (replace and iteration compose them: quadratic at worst, never exponential). A call routed to std — a match flag REAL cannot honor, a $0 format, a traversal REAL does not model (basic_regex::uses_real_traversal) — runs on std’s backtracker under either policy.

Values:

enumerator strict#

Reject an ineligible pattern (throws regex_error with error_complexity). The default.

enumerator fallback#

Delegate an ineligible pattern to std::regex (backtracking — not ReDoS-safe).

Complexity#

A pattern the shim routes to REAL matches in guaranteed linear time – O(len(text)) – and never backtracks (ReDoS-safe). Which patterns route, and what the opt-in fallback changes, is exactly the compatibility contract.

Example#

Compiled and run by the example-check gate on every push:

  namespace rc = real::compat;

  const rc::regex   date {R"((\d{4})-(\d{2}))"};
  const std::string text {"released 2026-07-21"};

  rc::smatch m;
  if (rc::regex_search(text, m, date)) {
    std::cout << m[1].str() << "/" << m[2].str() << "\n";  // 2026/07
  }

See also#