【问题标题】:How to implement a lazily evaluated function on two C++20 ranges?如何在两个 C++20 范围内实现惰性求值函数?
【发布时间】:2020-06-28 19:24:36
【问题描述】:

Eric Niebler 提供了一个zip_with 函数。

但是,既然 C++20 支持范围,我想构建类似的东西。

filtertransform 的问题在于它们迭代了一个范围?

我该怎么做呢?我已经被这个问题困扰了一段时间,并且讨厌使用表达式模板来做同样的事情。

假设我有两个向量 M1{1,2,3} 和 M2{4,5,6}。

我想使用范围库来重载一个运算符以返回一个包含这两个矩阵相加的视图 - M1+M2 := {5,7,9}

使用ranges-v3,我可以执行auto sum = zip_with(std::plus,M1,M2);

上面的表达式是惰性求值的。如何使用 C++20 Ranges 重新创建此表达式?

【问题讨论】:

  • 您应该添加一个代码示例来显示您的意图。 两个 C++20 范围内的惰性求值函数可以用多种方式解释。
  • @super 也添加了示例。
  • 我不明白你在问什么。是不是:如何实现zip_with
  • @Barry 类似于 C++20 范围库
  • 好的,但是 range-v3 的 zip_with 在 C++20 范围内工作得很好,有什么问题?

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


【解决方案1】:

原理很简单。创建一个迭代器,为每个向量存储一个迭代器,当递增时,递增两个存储的迭代器,并且仅在取消引用时才进行加法。

这里有一段代码说明了原理:

template <class It1, class It2>
struct adder_iterator{
  It1 it1;
  It2 it2;

  decltype(auto)
  operator++(){
    ++it1; ++it2;
    return *this;
    }

  auto
  operator *()const{
    return *it1+*it2;
    }
  //....
  };

您还需要实现一个哨兵和一个视图(通过从std::view_interface 派生)。

标记是end 迭代器。您可以为此使用 adder_iterator 类。但是您可以考虑优化:在您的视图构造函数中,您确保最短的向量开始迭代器始终是 it1 end 然后只使用这个迭代器来测试迭代的结束。你应该试试看。

【讨论】:

  • 这就是我想要的。我了解视图部分,你能告诉我更多关于哨兵的信息吗?而且,我还需要实现一个适配器吗?
  • @AniketChowdhury 适配器对象仅用于获取流,如语法 "a_view | an_adaptor | an_other_adaptor" ...
  • @AniketChowdhury 哨兵只是一个“结束”迭代器,其类型不同于开始迭代器。它主要被使用,因为它使范围类算法更有效。例如,在这种情况下,在 zip_range 的愚蠢实现中,检查 adder_iterator 是否已到达末尾的测试可以是测试 it1 或 it2 中的任何一个是否已到达末尾。但是,如果两个迭代器都是 random_access_iterators,那就太过分了。
  • @AniketChowdhury 我第一次阅读哨兵是在 Niebler 博客:ericniebler.com
  • 另一件事,view_interface 派生类在哪里被调用。如果我理解的话,我们是从adder_view 构造函数调用adder_iterator。那是对的吗?看起来还是有点混乱。
【解决方案2】:

我不知道 c++20 中允许什么,但以下适用于 range-v3 的 cpp20 命名空间。

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

int main() {

  std::vector<int> m1 = {1, 2, 3};
  std::vector<int> m2 = {4, 5, 6};

  auto sum = ranges::cpp20::views::transform(m1, m2, std::plus{});

  for (auto i : sum)
      std::cout << i << " "; // 5 7 9
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-16
    • 2019-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    • 2011-01-31
    相关资源
    最近更新 更多