std::ranges::replace
replaces elements in a range, you want to replace a subrange with another subrange. As far as I know, there is currently no algorithm for it in the standard library.
Using std::regex
:
I would just use std::regex
:
std::string str{"The quick brown fox jumped over the lazy dog."};
std::cout << std::regex_replace(str,std::regex("the"), "a") << std::endl;
The quick brown fox jumped over a lazy dog.
https://godbolt.org/z/q4c6dzzPP
Using std::ranges
:
If you really really want to use std::ranges
, you could split your range at the given pattern, insert the replacement at the splits and then join the range.
Using std::ranges
in C++23:
C++23 conveniently provides a function std::views::join_with
(that hasn't been widely adapted yet as of the time of writing this):
auto replace_view(std::string_view str, std::string_view pattern, std::string_view replacement)
{
return str | std::views::split(pattern) | std::views::join_with(replacement);
}
https://godbolt.org/z/nd8zardE5
Using std::ranges
in C++20:
You can get it to work in C++20 as well, you just need to put in a bit more work:
auto replace_view(std::string_view str, std::string_view pattern, std::string_view replacement)
{
return str
// split at pattern
| std::views::split(pattern)
// prefix each subrange with the replacement
| std::views::transform(
[replacement](auto const& substr){
return std::string(replacement) + std::string(substr.begin(), substr.end());
}
)
// join the subranges to a single range
| std::views::join
// drop the first occurance of the replacement
| std::views::drop(replacement.size());
}
https://godbolt.org/z/j1WMWdW1h