【问题标题】:C++20 range-v3 and the zip_with view adapterC++20 range-v3 和 zip_with 视图适配器
【发布时间】:2023-03-14 00:54:01
【问题描述】:

使用诸如ranges::view::reverse 之类的惰性范围组合器,我可以为其提供单个参数(例如reverse(iota(0,3)));或者我可以使用它来调整使用operator| 的范围(例如iota(0,3) | reverse)。这种平价看起来相当规律。以下是空视图、一元视图和二元视图的示例:

#include <range/v3/all.hpp>
#include <iostream>

int main(int argc, char *argv[])
{
  using namespace ranges::view;
  std::cout <<        (iota(0,9) | reverse)      << ' ';
  std::cout << reverse(iota(0,9))                << '\n';

  std::cout <<        (iota(0,9) | chunk(4))     << ' ';
  std::cout <<   chunk(iota(0,9),4)              << '\n';

  std::cout <<        (iota(0,9) | replace(5,0)) << ' ';
  std::cout << replace(iota(0,9),5,0)            << '\n';
  return 0;
}

我注意到ranges::view::zip_with 组合子只能用于第二种(非适配器)形式;如zip_with(std::plus{},iota(0,9),iota(0,9))zip_with 不能被定义为与 operator| 一起使用是否有技术原因? range-v3 库中惰性范围组合器的参数是否有规范排序?

我正在使用 range-v3 库的最新版本 (v0.4.0)。

【问题讨论】:

  • 如何将两个范围通过管道传输到单个 zip_view
  • 你只需要管其中一个。

标签: c++ c++20 range-v3


【解决方案1】:

在 range-v3 中,r | adapter(x)adapter(r, x) 的含义相同,这是一个非常普遍的约定。 (实际上,甚至还有一种编程语言 Elixir,r |&gt; adapter(x) 实际上直接计算为 adapter(r, x))。

zip_with 的问题在于,正如您所指出的,它的用法是:

zip_with(std::plus{},iota(0,9),iota(0,9))

这意味着与operator| 的逻辑分离将是:

std::plus{} | zip_with(iota(0,9),iota(0,9))

但是,这不是左侧的范围。那是一些二元运算符。 range-v3 是关于链接 ranges 的。在所有其他情况下,它是出现在| 左侧的范围。因此,虽然这在技术上并不难做到,但它似乎是一种本质上不同的事情。

【讨论】:

  • 如果你的第一个范围也是可调用的,你也会遇到问题,因为你现在在 rhs 上有zip_with(deduced_potentially_callable, deduced_range)
  • 感谢@Barry 的输入。在那种情况下,zip_with 可以被定义为最后接受它的函数参数;即zip_with(iota(0,9),iota(0,9),std::plus{}).
  • @user2023370 是的,但是 (a) zip_with 采用可变数量的范围,因此必须先执行函数类型,并且 (b) 从其他语言中熟悉函数先执行(例如Haskell)。
  • 所以也许约定应该是r | adapter(x)adapter(x,r) 的意思相同?
猜你喜欢
  • 2021-07-13
  • 2021-10-18
  • 1970-01-01
  • 2015-12-29
  • 1970-01-01
  • 2021-06-21
  • 2012-10-25
  • 1970-01-01
  • 2020-08-25
相关资源
最近更新 更多