kab*_*nus 9 c++ c++20 std-ranges
有些用法|看起来更像函数管道或链接,而不是按位或,与 c++20 范围结合使用。像:
#include <ranges>
#include <vector>
template<typename T>
std::vector<T> square_vector(const std::vector<T> &some_vector) {
auto result = some_vector | std::views::transform([](T x){ return x*x; };
return {result.begin(), result.end()};
}
Run Code Online (Sandbox Code Playgroud)
显然,该|运算符不是按照通常意义上的按位或来使用的。它从什么时候开始工作,在什么类型的函数/对象上工作?这些像常规视图吗?有哪些注意事项?
kab*_*nus 10
这种函数链已在 C++20 范围中引入,最大的功能是允许对视图(更准确地说,可查看范围)上的操作进行延迟评估。这意味着转换视图的操作只会在迭代时对其起作用。
这种语义允许管道语法糖,以可读的方式放置迭代结果时会发生的情况。与此一起使用的函数基于范围适配器,它采用一个视图(可能还有其后的附加参数)并在迭代时对其进行转换(本质上返回另一个视图)。
管道语法是为这些称为范围适配器闭包的特殊子组保留的,它只采用单个视图,没有附加参数。这些可以是没有附加参数的适配器、绑定了多余参数的适配器,或者是某些库函数的结果,例如std::views::transformOP中的 。从 cpp23 开始,您也可以自己定义这些)。一旦我们有了其中一些,语法:
some_viewable_range | std::views::some_adaptor_closure | some_other_adaptor_closure
Run Code Online (Sandbox Code Playgroud)
相当于
some_other_adaptor_closure(std::views::some_adaptor_closure(some_viewable_range))
Run Code Online (Sandbox Code Playgroud)
它将在迭代返回的视图时评估管道。相似地,
some_vector | std::views::transform([](T x){ return x*x; });
Run Code Online (Sandbox Code Playgroud)
是相同的
std::views::transform([](T x){ return x*x; })(some_vector); // The first call returns the adaptor std::views::transform(some_vector, [](T x){ return x*x; }) with the second argument bound.
Run Code Online (Sandbox Code Playgroud)
但更具可读性。
与任何视图一样,您可以直接迭代它们。由于这是懒惰的,所以可能会发生不好的事情,例如:
template<typename T>
auto square_vector(const std::vector<T> &some_vector) {
return some_vector | std::views::transform([](T x){ return x*x; });
}
int main () {
for(auto val : square_vector(std::vector<int>{1, 2 ,3, 4, 5}))
std::cout << val << '\n';
}
Run Code Online (Sandbox Code Playgroud)
当您打印 时val,原始向量已不存在,因此链的输入消失了,并且从那里开始走下坡路。
要进一步深入研究范围和适配器的世界,您可以查看https://en.cppreference.com/w/cpp/ranges,以及它们所基于的原始库,https: //ericniebler.github.io/range- v3/ .
| 归档时间: |
|
| 查看次数: |
2693 次 |
| 最近记录: |