While a span
can be constructed from a range, a string_view
cannot be constructed from a range of chars.
Thus, for example, the following code is required:
// assume chars_span is a span of chars
std::cout << std::string_view(chars_span.data(), chars_span.size());
// or:
std::cout << std::string_view(chars_span.begin(), chars_span.end());
Instead of a simpler range-syntax that is not supported:
std::cout << std::string_view(chars_span);
Is there a reason for not having a constructor for string_view
that accepts a range of chars, or was it just overlooked or not considered important enough?
P1391r3 proposed this, though this was dropped in the version that was eventually adopted for C++20: P1391r4. The reason for the drop unfortunately is completely absent from the paper (indeed, the paper does not even mentioned that it was dropped).
However, a follow-up paper, P1989R0 presents the issue as what happens if we had a type like this (I modified the example slightly):
struct buffer {
buffer() {};
char const* begin() const { return data; }
char const* end() const { return data + 42; }
operator string_view() const {
return string_view(data, data + 2);
}
private:
char data[42];
};
Here, buffer
is convertible to string_view
. But the way in which it is convertible to string_view
differs in the way in which string_view
's range constructor would do it (the former gives you two chars, the latter gives you 42). As far as I am aware, nobody has actually pointed out the existence of such types.
Nevertheless, the direction was to ensure that those types continue to just work, so the new paper has a more complicated set of constraints for that particular constructor.
A more interesting example would be something like:
using ci_string = std::basic_string<char, case_insensitive_traits>;
ci_string value = "Hello";
std::string_view sv = value;
Any kind of straightforward range-based reasoning would allow the conversion from ci_string
to std::string
. A ci_string
is a perfectly good contiguous range of char
, without any weird conversion issues like the buffer
type from earlier. But while ci_string
should be convertible to basic_string_view<char, case_insensitive_traits>
, we probably wouldn't want to avoid it being convertible to just normal string_view
. That's unlikely to be intended, so it's something that we need to try to guard against.
This case is much more motivating for me than the buffer
case.