Distinguishing between rvalue Views and rvalue Containers

By : Yakk
Source: Stackoverflow.com

I am writing some container or iterable-based algorithms. Basically, I operate on objects that support for( : ) style iteration (I rarely use for( : ) directly, but follow how it looks up the begin and end iterators).

In the std library, most every iterable objects are containers. They both own their data, and they let you look at it.

When an algorithm takes a container by rvalue reference, this implies that the contents of the container are also free to be taken from. As an example, if I write concatinate which takes two vectors and returns a third, if both vectors are moved, we will want to reuse the first vector then use move_iterators to take the data out of the second vector for efficiencies sake.

However, with C++1y's string_view and types that are similar in conception, we have iterable objects that are not containers, but rather views into containers. Semantically, I believe views behave like pointers, so their "by-value" duplication is duplication of the view into the container, not the data they refer to. If I take a string_view style view by rvalue reference, that doesn't mean it owns the contents: moving from the contents is not justified, no more than moving the contents of a pointer just because the pointer itself is an rvalue.

Meanwhile, containers follow value semantics, and moving their contents because they are an rvalue is valid.

For string_view this isn't a problem, but I have written more generic view classes, such as contiguous_range_view, which lets you act on subsets of a vector or array or arr[] as if it was a non-mutable sized buffer.

These views do not always treat their contents as const, but they do not own their contents. So the view being an rvalue does not imply that their contents are rvalues!

My algorithms like concatinate run into problems here. Views are nearly indistinguishable from containers, and rvalue containers are valid to be moved-from, while rvalue views are not. And a function that returns a view by value is a good pattern, as views are semantically pointer-types.

I'm looking for a nice, clean way to distinguish between containers and views. Is there a plan to distinguish string_view in C++1y through some property or tag that I could emulate or hook into now? If not, is there a good pattern?

If I manage to block views from being moved-from accidentally, I will still need to be able to move from them sometimes, so I'll need a way to mark a view as being a move-from candidate other than being an rvalue reference. I suspect a make_move_range function might solve that problem (that takes an iterable range, and applies std::make_move_iterator to begin and end).

By : Yakk


Maybe this general pattern would help:

struct Container
    CopyIterator begin() 

If the goal is to distinguish between std::string and std::string_view, I would use something like this :

By : Vincent

This video can help you solving your question :)
By: admin