Я пробую интерфейс диапазона c ++ 20, и я добавил конструктор, который принимает диапазон в моем контейнероподобном типе.
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;
};
Версия с парой итераторов довольно проста. В els_(first, last);
он копирует элементы, если Iter - обычный итератор, и перемещает элементы, если Iter - подвижный итератор, такой как std::move_iterator<>
. Ответственность за передачу перемещаемых итераторов лежит на вызывающей стороне, если вызывающая сторона хочет, чтобы элементы были перемещены.
Однако в версии диапазона, хотя я могу проверить, указан ли сам диапазон в ссылке rvalue или ссылке lvalue, это не помогает проверить, может ли элемент быть перемещен или нет.
Допустим, у нас есть создатель диапазона, make_range()
, который берет контейнер и возвращает экземпляр прокси, который соответствует концепции диапазона. В следующем коде Range
конструктора является rvalue-ссылкой в обоих случаях, но очевидно, что элементы не должны перемещаться во втором случае.
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
Как я могу проверить, предназначен ли данный диапазон для копирования для перемещения?