是否检查范围中的元素是否可以移动? [英] check if elements of a range can be moved?

查看:14
本文介绍了是否检查范围中的元素是否可以移动?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试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。是用户定义的类型控制行为,这很好。

这篇关于是否检查范围中的元素是否可以移动?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆