问题
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.
回答1:
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.
回答2:
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
来源:https://stackoverflow.com/questions/39034413/why-string-view-instead-of-generalized-container-viewt