C++20中为何无法用|管道像其他视图函数一样调用views::reverse
问题原因
std::views::reverse本身是支持operator|链式调用的,你遇到的编译错误来自C++20下无参范围适配器的调用规则差异:
- 需要传入配置参数的范围适配器(比如
std::views::take(int)、std::views::transform(Callable)、std::views::filter(Callable)、std::views::take_while(Callable)):传入参数调用后会返回适配器闭包对象,该对象重载了operator|,可以和range完成链式拼接。 - 不需要任何配置参数的范围适配器(C20标准下的
std::views::reverse、std::views::join等):适配器本身就是合法的适配器闭包对象,不需要加括号调用。你代码中写的std::views::reverse()属于无参调用,C20标准库没有提供该重载,因此会触发编译错误。
实现方案
要实现输出b3、b4的效果,只需要去掉链式调用中reverse后面的空括号即可,修正后的完整代码如下:
#include <iostream> #include <vector> #include <string> #include <ranges> int main() { using std::string; using std::cout, std::endl; const std::vector<string> vec = { "A", "B", "a", "b", "b2", "a2", "a3", "b3", "b4" }; for (auto const& val : std::views::reverse(vec) | std::views::take_while([](const string& s) {return s.size() > 0 && s[0] == 'b'; }) | std::views::reverse ) { cout << val << endl; } }
使用你原来的编译命令g++ -std=c++20 main.cpp -o main即可正常编译运行,执行逻辑为:
- 第一次
reverse将原容器倒序,得到序列b4, b3, a3, a2, b2, b, a, B, A take_while从倒序序列开头截取首字符为b的元素,得到b4, b3- 第二次
reverse将截取后的序列再次倒序,得到目标序列b3, b4
注:C23标准为所有无参范围适配器补充了无参调用返回闭包的重载,在C23环境下写
std::views::reverse()也可以正常通过编译,但C++20环境下必须省略空括号。
内容的提问来源于stack exchange,提问作者FalcoGer
相关产品推荐
相关产品推荐

