I need to split a std::string
at all spaces. The resulting range should however transform it's element to std::string_view
s. I'm struggling with the "element type" of the range. I guess, the type is something like a c_str
. How can I transform the "split"-part into string_view
s?
#include <string>
#include <string_view>
#include "range/v3/all.hpp"
int main()
{
std::string s = "this should be split into string_views";
auto view = s
| ranges::view::split(' ')
| ranges::view::transform(std::string_view);
}
This answer is for ranges-v3 and c++17.
For a c++20/c++23 answer using std-ranges, see Peng's answer.
(One of) the problem here is that ranges::view::split
returns a range of ranges, and you cannot construct a std::string_view
directly from a range.
You want something like this:
auto view = s
| ranges::views::split(' ')
| ranges::views::transform([](auto &&rng) {
const auto size = ranges::distance(rng);
// &*rng.begin() is UB if the range is empty, so we need
// to check before using it
return size ? std::string_view(&*rng.begin(), size) : std::string_view();
});
There might be a better/easier way to do this but:
&*rng.begin()
will give you the address of the first character of the chunk in the original string.ranges::distance(rng)
will give you the number of characters in this chunk. Note that this is slower than ranges::size
but required here because we cannot retrieve the size of rng
in constant time.