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 vector
s and returns a third, if both vector
s are move
d, we will want to reuse the first vector
then use move_iterator
s 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
).