check if elements of a range can be moved?(是否检查范围中的元素是否可以移动?)
问题描述
我正在尝试C++20的Range接口,并且我添加了一个构造函数,该构造函数接受类容器类型的Range。
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<>,则它移动元素。如果调用方希望移动元素,则由调用方负责显式地给出可移动迭代器。
然而,在范围版本中,虽然我可以检查范围本身是在右值引用中还是在左值引用中给定的,但它无助于检查元素是否可以移动。
假设我们有一个范围标记make_range(),它接受一个容器并返回一个符合范围概念的代理实例。在下面的代码中,构造函数的Range在两种情况下都是右值引用,但显然在第二种情况下不应该移动元素。
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
如何检查给定范围是否用于复制以进行移动?
推荐答案
您不信任。您信任std::ranges::begin返回的迭代器,就像您信任迭代器Iter做正确的事情一样。您的第二个构造函数只能委托:
template <std::ranges::Range Range> // Constraints checked with the library concept
myclass(Range&& r) : myclass(std::ranges::begin(std::move(r)), std::ranges::end(std::move(r)))
{}
默认行为是复制,这是合理的。但由于std::ranges::begin是一个定制点对象,它可以通过ADL拾取用户定义的begin重载。对于用户定义的类型,此设置:
namespace myns {
class myclass { /* ... */ };
auto begin(std::vector<myclass>&& v) { return std::make_move_iterator(v.begin()); }
auto end(std::vector<myclass>&& v) { /* ... * }
}
将在向类构造函数传递右值向量时进行std::ranges::begin调用myns::begin。是用户定义的类型控制行为,这很好。
这篇关于是否检查范围中的元素是否可以移动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:是否检查范围中的元素是否可以移动?
基础教程推荐
- 我有静态或动态 boost 库吗? 2021-01-01
- 这个宏可以转换成函数吗? 2022-01-01
- 常量变量在标题中不起作用 2021-01-01
- 如何在 C++ 中初始化静态常量成员? 2022-01-01
- 如何通过C程序打开命令提示符Cmd 2022-12-09
- 如何检查GTK+3.0中的小部件类型? 2022-11-30
- 如何将 std::pair 的排序 std::list 转换为 std::map 2022-01-01
- 静态库、静态链接动态库和动态链接动态库的 .lib 文件里面是什么? 2021-01-01
- 在 C++ 中计算滚动/移动平均值 2021-01-01
- C++结构和函数声明。为什么它不能编译? 2022-11-07
