如何将 istream_view 收集到容器中?

2023-11-25

我试图为我的扩展实现一个通用的缩减操作c++20's ranges这将收集任何元素range到给定的容器中。为了实现这一点,我首先创建了一个虚拟类型来提取template template参数并提供operator|用于梳理一个range用它:

template <template <typename> typename T>
struct to_fn { };

template <template <typename> typename T>
inline constexpr detail::functors::to_fn<T> to;

template <template <typename> typename T>
auto operator|(std::ranges::range auto&& rng, detail::functors::to_fn<T>) {
    return T(std::ranges::begin(rng), std::ranges::end(rng));
}

测试如下:

int main() {
    using namespace std::ranges;
    std::vector<int> vec = {1, 2, 3, 4, 5};
    auto set = vec | to<std::set>;
    static_assert(std::same_as<decltype(set), std::set<int>>);
    assert(equal(vec, set));
}

代码执行完毕,没有任何问题。

但是,当与以下命令一起使用时,代码无法编译std::ranges::istream_view:

int main() {
    using namespace std::ranges;
    std::ifstream input_file("input.txt");
    auto vec = istream_view<int>(input_file) | to<std::vector>;
}

This fails编译时出现了大量错误,我认为其中最重要的是:

note:   deduced conflicting types for parameter '_InputIterator' ('std::ranges::basic_istream_view<int, char, std::char_traits<char> >::_Iterator' and 'std::default_sentinel_t')
122 |   return T(std::ranges::begin(rng), std::ranges::end(rng));
    |          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

这对我来说很有意义。容器要求用于通过采用其中两个的构造函数来构造它们的迭代器是同类型的.

但没关系 - 就是这样std::ranges::views::common_view是为.所以我尝试修改operator| to:

template <template <typename> typename T>
auto operator|(std::ranges::range auto&& rng, detail::functors::to_fn<T>) {
    auto common = rng | std::ranges::views::common;
    return T(std::ranges::begin(common), std::ranges::end(common));
}

再说一次,failed编译时出现的错误较少,我认为其中最相关的是:

note: the expression 'is_constructible_v<_Tp, _Args ...> [with _Tp = std::ranges::basic_istream_view<int, char, std::char_traits<char> >::_Iterator<int, char, std::char_traits<char> >; _Args = {std::ranges::basic_istream_view<int, char, std::char_traits<char> >::_Iterator<int, char, std::char_traits<char> >&}]' evaluated to 'false'
139 |       = destructible<_Tp> && is_constructible_v<_Tp, _Args...>;
    |                              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

我不太明白这个错误表明了什么,但我想这意味着istream_view不能被复制构造。对我来说有点道理。


But I really wish I could have this generic to "functor". I figured that it's okay to loop over istream_view with range-based for and add elements to the chosen container, when we deduce that we are dealing with an input range1.

所以我尝试了这个:

template <template <typename> typename T>
auto operator|(std::ranges::range auto&& rng, detail::functors::to_fn<T>) {
    using namespace std::ranges;
    using range_t = decltype(rng);
    const bool input_range = std::is_same_v<
            iterator_t<range_t>::iterator_category,
            std::input_iterator_tag>;
    if constexpr(input_range) {
        auto container = T<range_value_t<range_t>>();
        for (auto&& element : rng) {
            container.generic_add(element); // ???
        }
        return container;
    } else {
        auto common = rng | views::common;
        return T(begin(common), end(common));
    }
}

然后,除其他外,它告诉我:

error: 'iterator_category' is not a member of 'std::ranges::iterator_t<std::ranges::basic_istream_view<int, char, std::char_traits<char> >&&>'
125 |             iterator_t<range_t>::iterator_category,
    |                                  ^~~~~~~~~~~~~~~~~

这不是唯一的问题。通常还存在向任何容器添加元素的问题。构造函数采用range据我所知,这是唯一通用的方法good向容器添加元素的方法。

我觉得必须有一种正确且更简单的方法来完成我想做的事情。奖励积分如果to也适用于非模板,即我不仅可以这样做to<std::vector>但是也to<std::string>。在第一种情况下,它将推断元素并创建所需的实例化std::vector,但在第二种情况下,它将获取所有元素并初始化一个std::string和那些。我怎样才能做到这一点?


1 This assumes that the actual problem lies in the fact that we are using input range. I am not sure whether that's the case. I would love if someone could point out the possible error in my reasoning.


For c++23, ranges::to (P1206R7)将正确处理仅移动视图。


这假设实际问题在于我们正在使用输入范围.

问题不在于它是一个输入范围,问题在于std::ranges::istream_view<int>及其迭代器类型都是仅移动的。

在 C++17 中,所有迭代器都必须是可复制的。这一限制在 C++20 中得到了放松,我们现在可以拥有仅移动迭代器和仅移动视图。但必须更改代码才能支持 -std::vector的迭代器对构造函数仍然基于 C++17 迭代器模型,该模型会复制迭代器,因此它不能用于std::ranges::istream_view<int>::iterator.

要点是common_view是采用 C++20 范围(其哨兵类型与其迭代器类型不同),并通过为迭代器和哨兵生成相同的类型来使其适应 C++17 算法。但这里的重点是使用 C++17 算法,因此它必须遵守 C++17 迭代器要求。这些要求包括可复制性,所以common_view被声明为,从[范围.常见.视图]:

namespace std::ranges {
  template<view V>
    requires (!common_range<V> && copyable<iterator_t<V>>)
  class common_view : public view_interface<common_view<V>> {

这就是为什么rng | views::common不会为你编译,common需要可复制性(在迭代器/哨兵类型不同的情况下,就像它们在这里所做的那样),而您没有(您也应该转发rng,因为即使views::common不需要直接复制,你所做的实际上是复制它,所以会单独失败)。

实在没办法适应std::ranges::istream_view<int>这样你就可以使用vector<int>的迭代器对构造函数。我们需要改变vector以某种方式允许这种构造起作用(这现在肯定对您没有帮助),或者您必须通过执行以下等效操作来处理这种情况:

std::vector<int> v;
for (int e : rng) {
    v.push_back(e);
}
return v;

虽然那必须看起来像s.insert(e)为了std::set case.

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

如何将 istream_view 收集到容器中? 的相关文章

随机推荐

  • python 3.5 asyncio和aiohttp Errno 101网络无法访问

    我在 Ubuntu 16 上使用 python 3 5 我正在尝试使用 aiohttp 编写一个简单的客户端 这是我的代码 我把它从here 这是第一个代码示例 禁用了 ssl 检查 import aiohttp import asynci
  • 如何使单词边界 \b 与破折号不匹配

    我将代码简化为我遇到的具体问题 import re pattern re compile r bword b result pattern sub lambda x match word word 我正进入 状态 match match 但
  • 从屏幕中心获取位置 Swift MapKit

    我是 Swift 编程新手 我正在尝试构建一个应用程序 我可以使用 MapKit 和 Swift 2 获取视图中心的坐标 我已经可以获得当前位置 但如果我在地图上移动 我需要将位置设置为新点 该点将成为屏幕的中心 你能帮我解决这个问题吗 R
  • Swift 将每隔一个项目追加到数组中

    我有一个快速数组 Monthdata 我想将每个第二个值附加到我的月份数组中 var monthData let months Jul 12 Aug 12 Sep 12 Oct 12 for month in months self mon
  • 离开作用域时调用函数

    离开作用域时自动调用函数的最优雅的解决方案是什么 我目前的方法 见下文 works但我想应该有一些更通用的东西 比如为此编写一个自定义类 include
  • 为什么函数需要在定义或使用之前声明?

    在 C 中它是可选的 在C 中一 MUST 在使用 定义函数之前声明它 为什么会这样呢 有什么需要吗 我们不会在 C 或 Java 中这样做 有趣的是当我们在的时候defining一个函数 即使定义本身有一个声明 我们也需要声明 天知道为什
  • ActionScript 中的语法突出显示库

    我让用户在我的 Flex3 Flash 10 应用程序中输入一些代码 我想进行语法突出显示 有没有开源库可以帮助我 我需要 Lua 语法支持 但如果库有一个合理的接口来执行此操作 我可以自己添加它 2009 年 1 月 21 日更新 查看A
  • 如何本地化 Django 应用程序的内容

    嘿 我目前正在为我的学习开发一个 django 应用程序 并且已经到了 l18n 的地步 本地化网站本身非常容易 但现在我必须允许用户翻译应用程序的动态内容 用户可以将 产品 保存在数据库中并为其提供名称和描述 但由于整个站点应该本地化 因
  • R 在 Mac OS X Yosemite 中冻结

    我遇到了这个问题 并且没有关于如何解决这个错误的明确解释 每当我尝试保存使用 R 内部编辑器编写的文件时 OS X Mavericks 的最新版本 R v 3 1 2 就会在 Yosemite 中冻结 当您尝试时它也会冻结source一个函
  • 将 URL 解码为数组而不是字符串

    我目前正在使用 PayPals API 并希望将其响应之一从名称 值对转换为数组 到目前为止我已经用过urldecode 将响应解码为以下内容 email protected email protected MOREINFO lots mo
  • 如何跟踪和检查捆绑的 Ruby gem 中的依赖关系

    Bundler 将自动安装指定 gem 的任何依赖项 但它不会在标准输出中输出哪些依赖项映射到哪些 gem 当依赖项之一安装失败时 该信息非常有用 有没有办法将 Bundler 设置得更详细并在安装时告知依赖项 我正在使用 Bundler
  • DTE.执行命令并等待

    我想使用宏来发布我的网络应用程序项目 小问题是 DTE ExecuteCommand 异步运行 我需要等待命令完成 Example DTE Windows Item Constants vsWindowKindSolutionExplore
  • T-SQL Case 语句以 newid() 作为随机源的奇怪行为

    我正在使用 SQL Server 2012 如果我执行以下操作来获取 1 3 范围内的随机数字列表 则效果很好 SELECT TOP 100 ABS CHECKSUM NEWID 3 1 value of rand FROM sys obj
  • 有没有办法将音频文件发送到语音转文本识别

    我想要 Android 语音识别系统分析音频文件 而不是来自麦克风的默认传入语音 有什么办法可以做到这一点吗 谢谢 cmusphinx sourceforge net wiki tutorialandroid 刚刚发现该链接听起来像是有人创
  • 如何使用 py2exe 减小 exe 的大小

    我使用 python 和 wxwidgets 开发了一个小程序 这是一个非常简单的程序 仅使用一个迷你框架在需要时显示一些信息 其余时间则不显示任何内容 仅在任务栏中显示一个图标 当我使用 py2exe 单文件 exe 模式 优化 构建 e
  • SQL Server 2005 如何清除查询执行计划

    各位程序员大家好 我有一个 SQL Server 2005 查询 第一次处理需要很长时间 第一次运行后 查询的运行速度要快得多 从一分钟到一秒 我知道 SQL Server 正在缓存执行计划 这个术语正确吗 我想做的就是明确这个执行计划 以
  • 异常与断言

    Java异常处理和使用异常处理有什么区别assert状况 众所周知 Assert 有两种类型 但我们什么时候应该使用assert关键词 使用断言进行代码中的内部逻辑检查 并使用正常异常来处理直接代码控制之外的错误情况 不要忘记断言可以打开和
  • 如何正确解析由空格分隔的文本文件

    下面是我的示例文本文件 这是我的架构文件 Sample File txt ColNameHeader True Format TabDelimited CharacterSet ANSI 这是我迄今为止编写的用于尝试读取上述示例文件的代码
  • python 是否允许我在运行时将动态变量传递给装饰器?

    我正在尝试在工作中集成一个非常旧的系统和一个较新的系统 我能做的最好的事情就是利用系统使用的 RSS 消防站类型提要 目标是使用此 RSS 源让其他系统在某些人做某事时执行某些操作 我的想法是在某些函数周围封装一个装饰器来检查用户 RSS
  • 如何将 istream_view 收集到容器中?

    我试图为我的扩展实现一个通用的缩减操作c 20 s ranges这将收集任何元素range到给定的容器中 为了实现这一点 我首先创建了一个虚拟类型来提取template template参数并提供operator 用于梳理一个range用它