I'm trying the range interface of c++20, and I added a constructor that takes a range in my container-like type.
class element {
...
};
class myclass {
public:
template <typename Iter>
myclass(Iter first, Iter last)
: els(first, last)
{ }
template <typename Range>
myclass(Range&& r);
private:
std::vector<element> els;
};
The iterator-pair version is quite easy. In els_(first, last);
, it copies the elements if Iter is a normal iterator, it moves the elements if Iter is a movable iterator such as std::move_iterator<>
. It's callers responsibility to explicitly give the movable iterators if the caller wants the elements moved.
In the range version, however, although I can check if the range itself is given in a rvalue reference or lvalue reference, it doesn't help checking if the element can be moved or not.
Let's say that we have a range maker, make_range()
, which takes a container and returns a proxy instance which complies the range concept. In the following code, Range
of the constructor is an rvalue reference in both cases but obviously the elements should not be moved in the second case.
std::list<element> list_of_elements{...};
myclass c(std::move(list_of_elements)); // should be moved
std::list<element> list_of_elements_to_be_reused{...};
myclass c(make_range(list_of_elements_to_be_reused)); // should not be moved
How can I check if the given range is for copying for moving?