垂直管有什么|在C++ 20和范围的背景下的平均值?
有|
的用法看起来更像是功能管道衬里或链接,而不是位于位置,或者与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()};
}
...显然|
运算符在通常的含义或位于位。从什么时候起作用,以及什么样的函数/对象?这些像常规观点吗?有什么警告?
There are usages of |
which look more like function pipe-lining or chaining rather than a bitwise or, seen in combination with the c++20 ranges. Things like:
#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()};
}
... where clearly the |
operator is not used in the usual sense of the bitwise or. Since when does it work, and on what sort of functions/objects? Are these like regular views? What are some caveats?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
C ++ 20范围已经引入了这种功能链接,其中最大的功能允许对视图的操作评估(更准确地说,可查看的范围)。这意味着转换视图的操作只会在迭代时对其作用。
这种语义允许使用管道语法糖,以可读的方式放置了结果迭代时会发生什么。与此相关的功能基于 范围适配器 ,该范围 进行视图(可能是之后的其他参数)并在其迭代时进行转换(本质上是返回另一个视图)。
管道语法保留给这些特殊的子组,称为 范围适配器闭合 ,它仅在没有其他参数的情况下进行单个视图。这些可以是适配器,没有其他参数,具有多余参数的适配器,也可以是某些库函数的结果,例如op中的
std :: views :: vistract :: transform
。由于CPP23您也可以)。一旦我们拥有其中的一些,语法:将这些关闭结合到一个可以重复使用的封闭中,并使用封闭方式,您最初是可见的范围:
这等同于
它会随着返回的视图的迭代评估管道。同样,
相同
与但更可读性
。与任何视图一样,可以直接迭代的视图。由于对管道的评估是懒惰的坏事,例如:
当您打印
val
时,原始向量不存在,因此链条的输入已经消失,并且掉了下来从那里到山。 在C ++ 23标准中解决了这个特定问题,请参见 https://open-std.org/jtc1/ssc22/wg21/wg21/wg21/docs/papers/2022/p2718r0.html - 但是,请注意在2024年6月。尽管如此,仍然必须要注意确保原始峰值的寿命超出视图的使用。要进一步研究范围和适配器的世界,您可以检查 https://en.cppreference.com/ w/cpp/ranges 和原始库基于, https:// https:// .github.io/range-v3/。
This sort of function chaining has been introduced with C++20 ranges, with the biggest feature allowing lazy evaluation of operation on views (more precisely, viewable ranges). This means the operation transforming the view will only act on it as it is iterated.
This semantic allows for the pipeline syntax sugar, putting in a readable way what will happen when the result is iterated. The functions this is used with are based on range adaptors, which take a view (and possibly additional arguments after it) and transform it as they are iterated (essentially returning another view).
The pipeline syntax is reserved for a special sub group of these called range adaptor closures, which only take a single view with no additional parameters. These can be either adaptors with no additional arguments, adaptors with the excess arguments bound, or the result of some library functions such as the
std::views::transform
in the OP. Since cpp23 you can also define these yourself). Once we have some of these, the syntax:combines such closures into one which can be re-used, and to use closures you pipe initially a viewable range:
which is equivalent to
which will evaluate the pipeline as the returned view is iterated. Similarly,
is the same as
but more readable.
The resulting view, like any view, can be iterated directly. Since evaluation of pipes is lazy bad things can happen such as:
by the time you get to print your
val
, the original vector does not exist, so the input to the chain is gone, and it goes down hill from there. This specific problem is fixed in the C++23 standard, see https://open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2718r0.html - but note support is not yet universal in June 2024. Care still must be take care though to ensure the lifetime of the original iterable is extended beyond the use of the view.To delve further into the world of ranges and adaptors you can check https://en.cppreference.com/w/cpp/ranges, and the original library these were based on, https://ericniebler.github.io/range-v3/.