This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++11 status.

### 727. `regex_replace()` doesn't accept `basic_string`s with custom traits and allocators

Section: 30.10.4 [re.alg.replace] Status: C++11 Submitter: Stephan T. Lavavej Opened: 2007-09-22 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [re.alg.replace].

View all issues with C++11 status.

Discussion:

`regex_match()` and `regex_search()` take `const basic_string<charT, ST, SA>&`. `regex_replace()` takes `const basic_string<charT>&`. This prevents `regex_replace()` from accepting `basic_string`s with custom traits and allocators.

Overloads of `regex_replace()` taking `basic_string` should be additionally templated on `class ST, class SA` and take `const basic_string<charT, ST, SA>&`. Consistency with `regex_match()` and `regex_search()` would place `class ST, class SA` as the first template arguments; compatibility with existing code using TR1 and giving explicit template arguments to `regex_replace()` would place `class ST, class SA` as the last template arguments.

[ Batavia (2009-05): ]

> Bill comments, "We need to look at the depth of this change."

> Pete remarks that we are here dealing with a convenience function that saves a user from calling the iterato-based overload.

> Move to Open.

[ 2009-07 Frankfurt: ]

> Howard to ask Stephan Lavavej to provide wording.

[ 2009-07-17 Stephan provided wording. ]

[ 2009-07-25 Daniel tweaks both this issue and 726. ]

> One relevant part of the proposed resolution below suggests to add a new overload of the format member function in the `match_results` class template that accepts two character pointers defining the `begin` and `end` of a format range. A more general approach could have proposed a pair of iterators instead, but the used pair of char pointers reflects existing practice. If the committee strongly favors an iterator-based signature, this could be simply changed. I think that the minimum requirement should be a `BidirectionalIterator`, but current implementations take advantage (at least partially) of the `RandomAccessIterator` sub interface of the char pointers.

> Suggested Resolution:

> [Moved into the proposed resloution]

[ 2009-07-30 Stephan agrees with Daniel's wording. Howard places Daniel's wording in the Proposed Resolution. ]

[ 2009-10 Santa Cruz: ]

> Move to Review. Chair is anxious to move this to Ready in Pittsburgh.

[ 2010-01-27 Moved to Tentatively Ready after 5 positive votes on c++std-lib. ]

Proposed resolution:

1. Change 30.3 [re.syn] as indicated:

   >     // 28.11.4, function template regex_replace:
   >     template <class OutputIterator, class BidirectionalIterator,
   >               class traits, class charT, class ST, class SA>
   >       OutputIterator
   >       regex_replace(OutputIterator out,
   >                     BidirectionalIterator first, BidirectionalIterator last,
   >                     const basic_regex<charT, traits>& e,
   >                     const basic_string<charT, ST, SA>& fmt,
   >                     regex_constants::match_flag_type flags =
   >                       regex_constants::match_default);

   >     template <class OutputIterator, class BidirectionalIterator,
   >               class traits, class charT>
   >       OutputIterator
   >       regex_replace(OutputIterator out,
   >                     BidirectionalIterator first, BidirectionalIterator last,
   >                     const basic_regex<charT, traits>& e,
   >                     const charT* fmt,
   >                     regex_constants::match_flag_type flags =
   >                       regex_constants::match_default);

   >     template <class traits, class charT, class ST, class SA,
   >               class FST, class FSA>
   >       basic_string<charT, ST, SA>
   >       regex_replace(const basic_string<charT, ST, SA>& s,
   >                     const basic_regex<charT, traits>& e,
   >                     const basic_string<charT, FST, FSA>& fmt,
   >                     regex_constants::match_flag_type flags =
   >                       regex_constants::match_default);

   >     template <class traits, class charT, class ST, class SA>
   >       basic_string<charT, ST, SA>
   >       regex_replace(const basic_string<charT, ST, SA>& s,
   >                     const basic_regex<charT, traits>& e,
   >                     const charT* fmt,
   >                     regex_constants::match_flag_type flags =
   >                       regex_constants::match_default);

   >     template <class traits, class charT, class ST, class SA>
   >       basic_string<charT>
   >       regex_replace(const charT* s,
   >                     const basic_regex<charT, traits>& e,
   >                     const basic_string<charT, ST, SA>& fmt,
   >                     regex_constants::match_flag_type flags =
   >                       regex_constants::match_default);

   >     template <class traits, class charT>
   >       basic_string<charT>
   >       regex_replace(const charT* s,
   >                     const basic_regex<charT, traits>& e,
   >                     const charT* fmt,
   >                     regex_constants::match_flag_type flags =
   >                       regex_constants::match_default);

2. Change 30.9 [re.results]/3, class template `match_results` as indicated:

   >     template <class OutputIter>
   >       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;

   >     template <class OutputIter, class ST, class SA>
   >       OutputIter
   >       format(OutputIter out,
   >              const string_typebasic_string<char_type, ST, SA>& fmt,
   >              regex_constants::match_flag_type flags =
   >                regex_constants::format_default) const;

   >     template <class ST, class SA>
   >       string_typebasic_string<char_type, ST, SA>
   >       format(const string_typebasic_string<char_type, ST, SA>& fmt,
   >              regex_constants::match_flag_type flags =
   >                regex_constants::format_default) const;

   >     string_type
   >     format(const char_type* fmt,
   >            regex_constants::match_flag_type flags =
   >              regex_constants::format_default) const;

3. Insert at the very beginning of 30.9.6 [re.results.form] the following:

   >     template <class OutputIter>
   >       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;

   > > 1 Requires: The type `OutputIter` shall satisfy the requirements for an Output Iterator (23.3.5.4 [output.iterators]).

   > > 2 Effects: Copies the character sequence `[fmt_first,fmt_last)` to `OutputIter out`. Replaces each format specifier or escape sequence in the copied range with either the character(s) it represents or the sequence of characters within `*this` to which it refers. The bitmasks specified in `flags` determine which format specifiers and escape sequences are recognized.

   > > 3 Returns: `out`.

4. Change 30.9.6 [re.results.form], before p. 1 until p. 3 as indicated:

   >     template <class OutputIter, class ST, class SA>
   >       OutputIter
   >       format(OutputIter out,
   >              const string_typebasic_string<char_type, ST, SA>& fmt,
   >              regex_constants::match_flag_type flags =
   >                regex_constants::format_default) const;

   > > 1 Requires: The type `OutputIter` shall satisfy the requirements for an Output Iterator (24.2.3).

   > > 2 Effects: Copies the character sequence `[fmt.begin(),fmt.end())` to `OutputIter out`. Replaces each format specifier or escape sequence in `fmt` with either the character(s) it represents or the sequence of characters within `*this` to which it refers. The bitmasks specified in `flags` determines what format specifiers and escape sequences are recognized Equivalent to `return format(out, fmt.data(), fmt.data() + fmt.size(), flags)`.

   > > 3 Returns: `out`.

5. Change 30.9.6 [re.results.form], before p. 4 until p. 4 as indicated:

   >     template <class ST, class SA>
   >       string_typebasic_string<char_type, ST, SA>
   >       format(const string_typebasic_string<char_type, ST, SA>& fmt,
   >              regex_constants::match_flag_type flags =
   >                regex_constants::format_default) const;

   > > Effects: Returns a copy of the string `fmt`. Replaces each format specifier or escape sequence in `fmt` with either the character(s) it represents or the sequence of characters within `*this` to which it refers. The bitmasks specified in flags determines what format specifiers and escape sequences are recognized. Constructs an empty string `result` of type `basic_string<char_type, ST, SA>`, and calls `format(back_inserter(result), fmt, flags)`.

   > > Returns: `result`

6. At the end of 30.9.6 [re.results.form] insert as indicated:

   >     string_type
   >       format(const char_type* fmt,
   >              regex_constants::match_flag_type flags =
   >                regex_constants::format_default) const;

   > > Effects: Constructs an empty string `result` of type `string_type`, and calls `format(back_inserter(result), fmt, fmt + char_traits<char_type>::length(fmt), flags)`.

   > > Returns: `result`

7. Change 30.10.4 [re.alg.replace] before p. 1 as indicated:

   >     template <class OutputIterator, class BidirectionalIterator,
   >               class traits, class charT, class ST, class SA>
   >       OutputIterator
   >       regex_replace(OutputIterator out,
   >                     BidirectionalIterator first, BidirectionalIterator last,
   >                     const basic_regex<charT, traits>& e,
   >                     const basic_string<charT, ST, SA>& fmt,
   >                     regex_constants::match_flag_type flags =
   >                       regex_constants::match_default);

   >     template <class OutputIterator, class BidirectionalIterator,
   >               class traits, class charT>
   >       OutputIterator
   >       regex_replace(OutputIterator out,
   >                     BidirectionalIterator first, BidirectionalIterator last,
   >                     const basic_regex<charT, traits>& e,
   >                     const charT* fmt,
   >                     regex_constants::match_flag_type flags =
   >                       regex_constants::match_default);

   > > Effects: [..]. If any matches are found then, for each such match, if `!(flags & regex_constants::format_no_copy)` calls `std::copy(m.prefix().first, m.prefix().second, out)`, and then calls `m.format(out, fmt, flags)` for the first form of the function and `m.format(out, fmt, fmt + char_traits<charT>::length(fmt), flags)` for the second form. [..].

8. Change 30.10.4 [re.alg.replace] before p. 3 as indicated:

   >     template <class traits, class charT, class ST, class SA,
   >               class FST, class FSA>
   >       basic_string<charT, ST, SA>
   >       regex_replace(const basic_string<charT, ST, SA>& s,
   >                     const basic_regex<charT, traits>& e,
   >                     const basic_string<charT, FST, FSA>& fmt,
   >                     regex_constants::match_flag_type flags =
   >                       regex_constants::match_default);

   >     template <class traits, class charT, class ST, class SA>
   >       basic_string<charT, ST, SA>
   >       regex_replace(const basic_string<charT, ST, SA>& s,
   >                     const basic_regex<charT, traits>& e,
   >                     const charT* fmt,
   >                     regex_constants::match_flag_type flags =
   >                       regex_constants::match_default);

   > > Effects: Constructs an empty string `result` of type `basic_string<charT, ST, SA>`, calls `regex_replace(back_inserter(result), s.begin(), s.end(), e, fmt, flags)`, and then returns `result`.

9. At the end of 30.10.4 [re.alg.replace] add the following new prototype description:

   >     template <class traits, class charT, class ST, class SA>
   >       basic_string<charT>
   >       regex_replace(const charT* s,
   >                     const basic_regex<charT, traits>& e,
   >                     const basic_string<charT, ST, SA>& fmt,
   >                     regex_constants::match_flag_type flags =
   >                       regex_constants::match_default);

   >     template <class traits, class charT>
   >       basic_string<charT>
   >       regex_replace(const charT* s,
   >                     const basic_regex<charT, traits>& e,
   >                     const charT* fmt,
   >                     regex_constants::match_flag_type flags =
   >                       regex_constants::match_default);

   > > Effects: Constructs an empty string `result` of type `basic_string<charT>`, calls `regex_replace(back_inserter(result), s, s + char_traits<charT>::length(s), e, fmt, flags)`, and then returns `result`.