I've found string_view from new C++17 standard a bit redundant.
We've got a quite verbose collection of simple mechanisms for passing data to callee, without much overhead and now there is one another which is also specific only to one container type.
I don't understand why providing this machinery only for string and not some more generalized type for other containers. One sensible answer is that we've already had these kinds of solutions. For example in C++17 and beyond presentation string_view is explained as observer_ptr<T> (or T*) for string
.
Please state the arguments against a more general container_view, in contrast to the string_view introduced by C++17.
string_view is useful when you want to avoid unnecessary copies. String_views are less memory-intensive to construct and copy. The creation of string_view from literals does not require a dynamic allocation.
So, frequently, you can pass string_view by reference and get away with it. But you should pass string_view by value, so that the compiler doesn't have to do those heroics on your behalf. And so that your code-reviewer doesn't have to burn brain cells pondering your unidiomatic decision to pass by reference.
The std::string_view, from the C++17 standard, is a read-only non-owning reference to a char sequence. The motivation behind std::string_view is that it is quite common for functions to require a read-only reference to an std::string-like object where the exact type of the object does not matter.
A typical implementation of a string_view needs two pieces of information. A pointer to the character sequence and its length. The character sequence can be both a C++ or a C-string. After all, std::string_view is a non-owning reference to a string.
A generalized container_view
is more properly called a range. We have a TS en-route devoted entirely to range concepts.
Now, we have string_view
as a separate type because it has a specialized, string-specific interface to match basic_string
's string-specific interface. Or at least, to match the const/non-allocating interfaces.
Note that container_view
or whatever you called it would be incapable of erasing its connection to the container that generated it. Or at least, not without paying type-erasure overhead on each access/operation.
By contrast, string_view
is based on const char*
s and integers. That class doesn't care where the string came from; it provides a view into a contiguous array of characters no matter who owns it. It can do this because it knows that the source is a contiguous array, and therefore uses pointers as the core of its iterator.
You can't do that for arbitrary containers. Your container_view<vector>
would have different iterators from container_view<list>
or whatever. It would have to. Which means if you take a container_view
as a function parameter, you must either pick a specific container to use (forcing the user to provide exactly that container type), make your function a template, or use a type-erased iterator range (thus being slower).
There are also post-C++17 proposals for the GSL types span
and mdspan
. The former represents a modifiable "view" of a contiguous array. The latter represents a modifiable "view" of a contiguous array that you treat as multi-dimensional.
string_view
offers more than a simple pointer on string.
You need to look at it as more than a simple non-owning pointer: if that's all it were, string_view
couldn't allow you to "slice" parts of the string, and apply operations to it (while still being a view; thus not incurring the cost of copy):
char *s = "welcome to stackoverflow";
auto s = std::string_view{s + 8, 2}; // a view on "to"
// you can then apply many operations on this view, that wouldn't make sense more on your general non_owning<T>:
s.remove_prefix(std::min(s.find_first_not_of(" "), s.size()));
// it also "inherits" (copies the API) a lot directly from std::basic_string
auto view2 = s.substr(3, 4); // a generic non-owning ptr would copy here, instead of giving you a new view
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With