regex_replace()
overloadsSection: 28.6.10.4 [re.alg.replace] Status: NAD 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 NAD status.
Discussion:
Two overloads of regex_replace()
are currently provided:
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 basic_string<charT>& fmt, regex_constants::match_flag_type flags = regex_constants::match_default); template <class traits, class charT> basic_string<charT> regex_replace(const basic_string<charT>& s, const basic_regex<charT, traits>& e, const basic_string<charT>& fmt, regex_constants::match_flag_type flags = regex_constants::match_default);
const charT *
are provided for regex_match()
and
regex_search()
, but not regex_replace()
. This is inconsistent.The absence of const charT *
overloads prevents ordinary-looking code from compiling, such as:
const string s("kitten"); const regex r("en"); cout << regex_replace(s, r, "y") << endl;
The compiler error message will be something like "could not deduce template argument for 'const std::basic_string<_Elem> &' from 'const char[1]'".
Users expect that anything taking a basic_string<charT>
can also take a
const charT *
. In their own code, when they write a function taking
std::string
(or std::wstring
), they can pass a const char *
(or const
wchar_t *
), thanks to basic_string
's implicit constructor. Because the
regex algorithms are templated on charT
, they can't rely on
basic_string
's implicit constructor (as the compiler error message
indicates, template argument deduction fails first).
If a user figures out what the compiler error message means, workarounds
are available - but they are all verbose. Explicit template arguments
could be given to regex_replace()
, allowing basic_string
's implicit
constructor to be invoked - but charT
is the last template argument, not
the first, so this would be extremely verbose. Therefore, constructing
a basic_string
from each C string is the simplest workaround.
basic_string
s can
impose performance costs that could be avoided by a library
implementation taking C strings and dealing with them directly.
(Currently, for replacement sources, C strings can be converted into
iterator pairs at the cost of verbosity, but for format strings, there
is no way to avoid constructing a basic_string
.)
[ Sophia Antipolis: ]
We note that Boost already has these overloads. However, the proposed wording is provided only for 28.6.10.4 [re.alg.replace]; wording is needed for the synopsis as well. We also note that this has impact on
match_results::format
, which may require further overloads.
[ 2009-07 Frankfurt: ]
Daniel to tweak for us.
[ 2009-07-25 Daniel tweaks both this issue and 727. ]
This is solved by the proposed resolution of 727.
[ 2009-10 Santa Cruz: ]
Leave Open. Though we believe this is solved by the proposed resolution to 727.
[ 2010-01-27 Moved to Tentatively NAD after 5 positive votes on c++std-lib. Rationale added below. ]
Rationale:
Solved by 727.
Proposed resolution:
Provide additional overloads for regex_replace()
: one additional
overload of the iterator-based form (taking const charT* fmt
), and three
additional overloads of the convenience form (one taking const charT*
str
, another taking const charT* fmt
, and the third taking both const
charT* str
and const charT* fmt
). 28.6.10.4 [re.alg.replace]:
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 basic_string<charT>& 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> basic_string<charT> regex_replace(const basic_string<charT>& s, const basic_regex<charT, traits>& e, const basic_string<charT>& fmt, regex_constants::match_flag_type flags = regex_constants::match_default); template <class traits, class charT> basic_string<charT> regex_replace(const basic_string<charT>& 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> basic_string<charT> regex_replace(const charT* s, const basic_regex<charT, traits>& e, const basic_string<charT>& 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);