使用有状态 lambda 和 std::views::drop 的范围转换
Range transformations with stateful lambdas and std::views::drop
这是我第一次深入研究新的 <ranges>
库,我尝试了一个小实验,将 std::views::transform
与有状态的 lambda 相结合,'piping' 结果范围为 std::views::drop
:
#include <iostream>
#include <ranges>
#include <vector>
using namespace std;
int main() {
auto aggregator = [sum = 0](int val) mutable
{
return sum += val;
};
vector<int> data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
cout << "Expected:\n";
int sum = 0;
for (int val : data) {
cout << (sum += val) << ' ';
}
cout << '\n';
cout << "Transformation:\n- - - ";
for (int val : data | views::transform(aggregator) | views::drop(3)) {
cout << val << ' ';
}
cout << '\n';
}
输出为:
Expected:
1 3 6 10 15 21 28 36 45 55
Transformation:
- - - 4 9 15 22 30 39 49
现在,每个预期输出和实际输出之间的差异是 1 + 2 + 3 = 6。我猜这是惰性计算范围的结果导致 std::views::drop
忽略前三个转换.
有什么方法可以强制对我删除的三个元素的 aggregator
仿函数求值?还是有状态的 lambda 和范围被认为是不兼容的?
transform_view
必须是纯函数。这被编入 the regular_invocable
concept:
The invoke function call expression shall be equality-preserving and shall not modify the function object or the arguments.
这对于允许 transform_view
不对其迭代器状态撒谎很重要。例如,前向迭代器应该允许多遍迭代。这意味着范围内每个迭代器位置的值必须独立于任何其他迭代器位置。如果转换仿函数不纯,那是不可能的。
请注意,所有 predicate
functors 也是 regular_invocable
。所以这也适用于 filter_view
和 take_while_view
.
注意算法transform
没有有这个要求。
这是我第一次深入研究新的 <ranges>
库,我尝试了一个小实验,将 std::views::transform
与有状态的 lambda 相结合,'piping' 结果范围为 std::views::drop
:
#include <iostream>
#include <ranges>
#include <vector>
using namespace std;
int main() {
auto aggregator = [sum = 0](int val) mutable
{
return sum += val;
};
vector<int> data{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
cout << "Expected:\n";
int sum = 0;
for (int val : data) {
cout << (sum += val) << ' ';
}
cout << '\n';
cout << "Transformation:\n- - - ";
for (int val : data | views::transform(aggregator) | views::drop(3)) {
cout << val << ' ';
}
cout << '\n';
}
输出为:
Expected:
1 3 6 10 15 21 28 36 45 55
Transformation:
- - - 4 9 15 22 30 39 49
现在,每个预期输出和实际输出之间的差异是 1 + 2 + 3 = 6。我猜这是惰性计算范围的结果导致 std::views::drop
忽略前三个转换.
有什么方法可以强制对我删除的三个元素的 aggregator
仿函数求值?还是有状态的 lambda 和范围被认为是不兼容的?
transform_view
必须是纯函数。这被编入 the regular_invocable
concept:
The invoke function call expression shall be equality-preserving and shall not modify the function object or the arguments.
这对于允许 transform_view
不对其迭代器状态撒谎很重要。例如,前向迭代器应该允许多遍迭代。这意味着范围内每个迭代器位置的值必须独立于任何其他迭代器位置。如果转换仿函数不纯,那是不可能的。
请注意,所有 predicate
functors 也是 regular_invocable
。所以这也适用于 filter_view
和 take_while_view
.
注意算法transform
没有有这个要求。