如何在两个 C++20 范围上实现惰性求值函数?
How to implement a lazily evaluated function on two C++20 ranges?
Eric Niebler 提供了一个 zip_with
函数。
但是,既然 C++20 支持范围,我想构建类似的东西。
filter
和 transform
的问题是它们迭代了一个范围?
我该怎么做?我已经坚持了一段时间,并且不愿意为此使用表达式模板。
假设我有两个向量 M1{1,2,3} 和 M2{4,5,6}。
我想使用范围库将运算符重载到 return 包含这两个矩阵加法的视图 - M1+M2 := {5,7,9}
.
使用 ranges-v3,我可以执行 auto sum = zip_with(std::plus,M1,M2);
上面的表达式是惰性求值的。如何使用 C++20 范围重新创建此表达式?
我不知道 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
}
原理很简单。创建一个迭代器,为每个向量存储一个迭代器,当递增时,递增两个存储的迭代器,并且仅在取消引用时才进行加法。
这里有一段代码说明了原理:
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
class。但是你可以考虑优化:在你的视图构造函数中,你确保最短的向量 begin 迭代器总是 it1 end 然后只使用这个迭代器来测试迭代的结束。你应该试试看。
Eric Niebler 提供了一个 zip_with
函数。
但是,既然 C++20 支持范围,我想构建类似的东西。
filter
和 transform
的问题是它们迭代了一个范围?
我该怎么做?我已经坚持了一段时间,并且不愿意为此使用表达式模板。
假设我有两个向量 M1{1,2,3} 和 M2{4,5,6}。
我想使用范围库将运算符重载到 return 包含这两个矩阵加法的视图 - M1+M2 := {5,7,9}
.
使用 ranges-v3,我可以执行 auto sum = zip_with(std::plus,M1,M2);
上面的表达式是惰性求值的。如何使用 C++20 范围重新创建此表达式?
我不知道 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
}
原理很简单。创建一个迭代器,为每个向量存储一个迭代器,当递增时,递增两个存储的迭代器,并且仅在取消引用时才进行加法。
这里有一段代码说明了原理:
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
class。但是你可以考虑优化:在你的视图构造函数中,你确保最短的向量 begin 迭代器总是 it1 end 然后只使用这个迭代器来测试迭代的结束。你应该试试看。