如何检查范围内的元素是否应该移动?

2024-05-07

有一个类似的问题:检查范围内的元素是否可以移动? https://stackoverflow.com/questions/56096579/check-if-elements-of-a-range-can-be-moved

我认为其中的答案不是一个很好的解决方案。实际上,它需要所有容器的部分专业化。


我尝试过,但不确定是否检查operator*()足够。

// RangeType

using IteratorType = std::iterator_t<RangeType>;
using Type = decltype(*(std::declval<IteratorType>()));

constexpr bool canMove = std::is_rvalue_reference_v<Type>;

Update

这个问题可以分为两部分:

  1. STL 中的算法可以像std::copy/std::uninitialized_copy在接收右值元素时实际上避免了不必要的深度复制吗?
  2. 当收到一个r值范围,如何检查它是否是范围适配器 https://en.cppreference.com/w/cpp/ranges#Range_adaptor_objects like std::ranges::subrange,或装有所有权它的元素像std::vector?
template <typename InRange, typename OutRange>
void func(InRange&& inRange, OutRange&& outRange) {
    using std::begin;
    using std::end;
    std::copy(begin(inRange), end(inRange), begin(outRange));
    // Q1: if `*begin(inRange)` returns a r-value,
    //     would move-assignment of element be called instead of a deep copy?
}

std::vector<int> vi;
std::list<int> li;
/* ... */
func(std::move(vi), li2);
// Q2: Would elements be shallow copy from vi?
// And if not, how could I implement just limited count of overloads, without overload for every containers?
// (define a concept (C++20) to describe those who take ownership of its elements)

正如 @Nicol Bolas 、 @eerorika 和 @Davis Herring 指出的那样,Q1 不是问题,这也不是我感到困惑的问题。 (但我确实认为 API 很混乱,std::assign/std::uninitialized_construct可能是更理想的名字)

@alfC 对我的问题(Q2)做出了很好的回答,并给出了一个原始的观点。 (移动具有元素所有权的范围的习语)


总而言之,对于大多数当前容器(尤其是来自 STL 的容器)(以及每个范围适配器...),所有这些容器的部分专业化/重载函数是唯一的解决方案,例如:

template <typename Range>
void func(Range&& range) { /*...*/ }

template <typename T>
void func(std::vector<T>&& movableRange) {
    auto movedRange = std::ranges::subrange{
        std::make_move_iterator(movableRange.begin()),
        std::make_move_iterator(movableRange.end())
    };

    func(movedRange);
}

// and also for `std::list`, `std::array`, etc...

我明白你的意思。 我确实认为这是一个真正的问题。

我的答案是,社区必须确切地同意移动嵌套对象(例如容器)的含义。 无论如何,这需要容器实现者的合作。 而且,就标准集装箱而言,规格良好。

我对标准容器可以更改为“概括”“移动”的含义感到悲观,但这不能阻止新的用户定义的容器利用移动惯用语。 问题是据我所知,没有人深入研究过这个问题。

就像现在一样,std::move似乎暗示“浅”移动(顶部“价值类型”的一级移动)。 从某种意义上说,您可以移动整个事物,但不一定可以移动单个部分。 反过来,这使得尝试“std::move”非拥有范围或提供指针/迭代器稳定性的范围变得毫无用处。

一些图书馆,例如相关std::ranges简单地拒绝参考范围的右值,我认为这只是踢罐头。

假设你有一个容器Bag。 什么应该std::move(bag)[0] and std::move(bag).begin()返回?返回什么实际上是由容器的实现决定的。

很难想到通用的数据结构,如果数据结构很简单(例如动态数组),那么为了与以下内容保持一致structs (std::move(s).field) std::move(bag)[0]应该是一样的std::move(bag[0])然而,该标准已经强烈反对我的观点:https://en.cppreference.com/w/cpp/container/vector/operator_at https://en.cppreference.com/w/cpp/container/vector/operator_at现在改变可能为时已晚。

同样适用于std::move(bag).begin()根据我的逻辑,它应该返回一个move_iterator(或类似的东西)。

为了让事情变得更糟,std::array<T, N>按照我的预期工作(std::move(arr[0])相当于std::move(arr)[0])。 然而std::move(arr).begin()是一个简单的指针,因此它丢失了“转发/移动”信息!这是一团糟。

所以,是的,要回答你的问题,你可以检查是否using Type = decltype(*std::forward<Bag>(bag).begin());是一个右值,但通常不会作为右值实现。 也就是说,你必须抱有最好的希望并相信.begin and *以非常具体的方式实施。

通过(以某种方式)检查范围本身的类别,您可以更好地了解情况。 也就是说,目前您只能使用自己的设备:如果您知道bag绑定到一个 r 值,并且该类型在概念上是一个“拥有”值,您当前必须使用以下命令std::make_move_iterator.

我目前正在用我拥有的自定义容器进行很多实验。https://gitlab.com/correaa/boost-multi https://gitlab.com/correaa/boost-multi然而,通过尝试允许这一点,我打破了标准容器在移动方面的预期行为。 此外,一旦您处于非拥有范围的领域,您就必须使迭代器可以“手动”移动。

我发现从经验上来说,区分顶级动作很有用(std::move)和元素明智的移动(例如bag.mbegin() or bag.moved().begin())。 否则我会发现自己超载std::move如果有的话,这应该是最后的手段。

换句话说,在

template<class MyRange>
void f(MyRange&& r) {
   std::copy(std::forward<MyRange>(r).begin(), ..., ...);
}

事实是r绑定到右值并不一定意味着元素可以移动,因为MyRange可以简单地是“刚刚”生成的较大容器的非拥有视图。

因此,一般来说,您需要一个外部机制来检测是否MyRange是否拥有这些值,而不仅仅是检测“值类别”*std::forward<MyRange>(r).begin()正如你所提议的。

我想通过范围,人们可以希望在未来用某种类似适配器的东西来指示深度移动”std::ranges::moved_range" 或使用 3 参数std::move.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何检查范围内的元素是否应该移动? 的相关文章

  • 无法使用 strptime() 获取秒数

    我收到 YYYY MM DDThh mm ss S Z hh mm 这种格式的日期时间 我正在尝试使用复制该值strptime如下所示 struct tm time 0 char pEnd strptime datetime Y m dT
  • boost::multi_index_container 复合键中的 equal_range 与比较运算符

    我正在尝试从多索引容器查询结果 其中值类型是三个元素的结构 第一个值已给出 但第二个和第三个值必须大于或小于查询参数 经过搜索后 我发现必须实现自定义密钥提取器 并且这里的一些链接建议相同 但我无法实现它 boost multi index
  • C++:无法使用scoped_allocator_adaptor传播polymorphic_allocator

    我有一个vector
  • 自动从 C# 代码进行调试过程并读取寄存器值

    我正在寻找一种方法来读取某个地址的 edx 注册表 就像这个问题中所问的那样 读取eax寄存器 https stackoverflow com questions 16490906 read eax register 虽然我的解决方案需要用
  • 在 Xamarin Android 中将图像从 URL 异步加载到 ImageView 中

    我有一个包含多个项目的 ListView 列表中的每个项目都应该有一个与之关联的图像 我创建了一个数组适配器来保存每个列表项并具有我希望加载的图像的 url 我正在尝试使用 Web 请求异步加载图像 并设置图像并在加载后在视图中更新它 但视
  • fgets() 和 Ctrl+D,三次才能结束?

    I don t understand why I need press Ctrl D for three times to send the EOF In addition if I press Enter then it only too
  • Cygwin 下使用 CMake 编译库

    我一直在尝试使用 CMake 来编译 TinyXML 作为一种迷你项目 尝试学习 CMake 作为补充 我试图将其编译成动态库并自行安装 以便它可以工作 到目前为止 我已经设法编译和安装它 但它编译成 dll 和 dll a 让它工作的唯一
  • 跨多个控件共享事件处理程序

    在我用 C 编写的 Windows 窗体应用程序中 我有一堆按钮 当用户的鼠标悬停在按钮上时 我希望按钮的边框发生变化 目前我有以下多个实例 每个按钮一个副本 private void btnStopServer MouseEnter ob
  • C# 用数组封送结构体

    假设我有一个类似于 public struct MyStruct public float a 我想用一些自定义数组大小实例化一个这样的结构 在本例中假设为 2 然后我将其封送到字节数组中 MyStruct s new MyStruct s
  • 为什么模板不能位于外部“C”块内?

    这是一个后续问题一个答案 https stackoverflow com questions 4866433 is it possible to typedef a pointer to extern c function type wit
  • 使用安全函数在 C 中将字符串添加到字符串

    我想将文件名复制到字符串并附加 cpt 但我无法使用安全函数 strcat s 来做到这一点 错误 字符串不是空终止的 我确实设置了 0 如何使用安全函数修复此问题 size strlen locatie size nieuw char m
  • 如何在 Team Foundation 上强制发表有意义的签入评论?

    我有一个开发团队有一个坏习惯 他们写道poor签入评论 当我们必须在团队基础上查看文件的历史记录时 这使得它成为一场噩梦 我已经启用了变更集评论政策 这样他们甚至可以在签到时留下评论 否则他们不会 我们就团队的工作质量进行了一些讨论 他们很
  • 使用 LINQ 查找列表中特定类型的第一个元素

    使用 LINQ 和 C 在元素列表中查找特定类型的第一个项目的最短表示法是什么 var first yourCollection OfType
  • 检查 url 是否指向文件或页面

    我们需要以下内容 如果文件确实是文件 则从 URL 下载该文件 否则 如果它是一个页面 则什么也不做 举个简单的例子 我有以下命令来下载文件 My Computer Network DownloadFile http www wired c
  • 将应用程序从 Microsoft Access 迁移到 VB 或 C#.NET

    我目前正试图说服管理层需要将我们的应用程序之一移植到 NET 该应用程序已经发展成为 Access 中的一个庞然大物 SQL 后端 拥有 700 个链接表 650 个表单 子表单 130 个模块和 850 个查询 我几乎知道这样做的所有主要
  • 如何构建印度尼西亚电话号码正则表达式

    这些是一些印度尼西亚的电话号码 08xxxxxxxxx 至少包含 11 个字符长度 08xxxxxxxxxxx 始终以 08 开头 我发现这个很有用 Regex regex new Regex 08 0 9 0 9 0 9 0 9 0 9
  • 如何在内存中存储分子?

    我想将分子存储在内存中 这些可以是简单的分子 Methane CH4 C H bond length 108 7 pm H H angle 109 degrees But also more complex molecules like p
  • 如何使用 ReactiveList 以便在添加新项目时更新 UI

    我正在创建一个带有列表的 Xamarin Forms 应用程序 itemSource 是一个reactiveList 但是 向列表添加新项目不会更新 UI 这样做的正确方法是什么 列表定义 listView new ListView var
  • C++ 成员函数中的“if (!this)”有多糟糕?

    如果我遇到旧代码if this return 在应用程序中 这种风险有多严重 它是一个危险的定时炸弹 需要立即在应用程序范围内进行搜索和销毁工作 还是更像是一种可以悄悄留在原处的代码气味 我不打算writing当然 执行此操作的代码 相反
  • 如何连接字符串和常量字符?

    我需要将 hello world 放入c中 我怎样才能做到这一点 string a hello const char b world const char C string a hello const char b world a b co

随机推荐

  • 如何在 Android Studio 中立即获取 LivaData 的值?

    savedRecordFileName是一个变量LivaData
  • 默认启动器图标大小应该是多少

    我参考了文档http developer android com guide practices ui guidelines icon design html icon sets http developer android com gui
  • 自定义 OpenLayers 控件

    如何轻松自定义 OpenLayers 地图控件 或者至少 如何最小化控件的高度 谢谢 附言 有 CSS 覆盖吗 您可以对任何 openLayers 控件进行子类化 我刚刚通过对 PanZoomBar panZoomBar js 进行子类化
  • 如何为多个 Android 商店支持我的 Android 应用程序?

    我最近开始在 Google Android Market 上销售我的 Android 应用程序 并实施他们的应用程序许可方案以防止未经授权使用我的应用程序 我现在正计划将其发布到 Amazon Android 应用商店 并且想知道维护我的应
  • C# 资源文件中的 Tab 键切换

    如何向字符串资源添加制表符 t text 不起作用 您必须显式添加制表符 最简单的方法可能是在记事本中键入字符串 显式设置制表符而不是使用转义字符 并将文本复制并粘贴到资源编辑器中 对于换行符 您也会遇到类似的问题 添加换行符的最简单方法是
  • 如何在ios中重置触摸、触摸移动的NSTimer

    我正在开发一个应用程序 其中我必须在 3 秒后隐藏控制按钮 所以我使用 NSTimer 编写代码 然后开始触摸 它可以工作 但问题是 当我再次触摸任何其他按钮时 我的计时器不会重置 即使我像拖动一样移动我的触摸示例 如果我拖动或移动触摸 它
  • 更改 RMarkdown 中的块背景颜色

    我希望某个代码块以不同的颜色 例如红色 突出显示 以表明这是不好的做法 如果我使用的是 Rnw 我可以添加块选项background red 并得到我想要的 但这似乎不起作用 Rmd 我的猜测是 我需要制作一个自定义 css 样式表 尽管我
  • 使用 javascript/jQuery 更改类的背景颜色属性

    这似乎是一个简单的问题 但没有任何解决办法 我正在尝试使用 javascript jQuery 动态更改某些文本的背景颜色 从白色或粉色到绿色 但由于某种原因它不起作用 文本使用名为 novice 的 CSS 类进行样式设置 这是CSS 这
  • 如何将 ng-repeat 与图像映射区域标签一起使用?

    我正在尝试使用 AngularJS 创建可点击的汽车配置文件 一旦我将区域标签属性移动到 auto parts json 并将它们与 ng repeat 中的适当属性绑定 那么它就无法工作 如何修复它 请在全页预览中测试元素 var app
  • 在设计电子邮件主题中添加动态价值

    好吧 我看过很多关于自定义设计电子邮件主题的讨论 但似乎没有一个能解决我想要的问题 目前我的确认电子邮件主题为 确认您的 Qitch com 帐户 我想自定义此电子邮件主题并在其中添加用户名的动态值 这样如果用户ALEX注册一个帐户 他应该
  • Opencv matchTemplate 和 np.where():仅保留唯一值

    继带有马里奥硬币的 opencv 教程 https opencv python tutroals readthedocs io en latest py tutorials py imgproc py template matching p
  • 配置Apache将SSL客户端证书发送到后端服务器

    我想配置 Apache 以便它接收客户端证书 并将其传递到另一台服务器 我在用着 Windows 上的 Apache 2 0 65 后端服务器是基于 apache 的解决方案 IBM HTTP Server 我尝试了这个配置
  • 使用 Bloomberg .Net API 的每小时数据

    我正在努力解决使用 Net API 3 0 从 Bloomberg 获取每小时开盘价 最高价 最低价和最后价格快照的逻辑 我已经用谷歌搜索了很多次 但没有运气 对此的任何帮助将不胜感激 我试图在 Bloomberg Net API C 中找
  • Google 测试中没有模拟的 EXPECT_CALL

    有没有办法通过 GoogleTest for c 测试函数调用而不创建模拟对象 例如我们有以下生产代码 if a method x 我想测试一下是否method在这种情况下将被调用a是真的并且a是假的 我想构建一个与 Google Test
  • 启动应用程序时,“npm start”和“node app.js”之间的区别?

    我已经使用命令安装了一个应用程序express new filename 我刚刚了解到您可以使用以下方式启动应用程序 npm start 到目前为止我已经使用过 node app js 启动我的服务器 有人知道两者有什么区别吗 谢谢 来自m
  • Highcharts 工具提示裁剪

    我正在使用高图表 但遇到了较大的工具提示在 SVG 外部元素处被裁剪的问题 如下图所示 选项useHTML工具提示和 xAxis 设置为 true 因为我正在应用一些自定义 CSS 这些元素 有没有办法让工具提示不被裁剪 我的 highch
  • AngularJS 货币过滤器:如果金额中没有美分,我可以删除 .00 吗?

    我正在关注这个 http docs angularjs org api ng filter currency http docs angularjs org api ng filter currency当我在字段中输入 1234 56 时
  • 使用 JScrollPane 和 JLayeredPane 进行 Swing GUI 设计

    我想要一个如下图所示的 GUI 设置 The JLayeredPane应始终具有相同的大小 但是JPanel和JScrollPane可以改变尺寸 我需要JScrollPane能够显示JLayedPane通过单击箭头 如果JPanel and
  • 具有桌面应用程序安全性的 OAuth2

    我有一个 Electron 应用程序 它基本上是一个 Google Drive 客户端 我打算使用 OAuth 2 但是 Google API 要求我在生成 client secret 的地方注册我的应用程序 由于这是一个桌面应用程序 因此
  • 如何检查范围内的元素是否应该移动?

    有一个类似的问题 检查范围内的元素是否可以移动 https stackoverflow com questions 56096579 check if elements of a range can be moved 我认为其中的答案不是一