views::istream或ranges::istream_view的正确语法是什么?
解决C++ ranges视图编译错误问题
我正在学习ranges::views,以下演示程序无法编译:
#include <iostream> #include <sstream> #include <string> #include <iterator> #include <ranges> #include <algorithm> namespace rng = std::ranges; struct CompleteLine { // Line Proxy for the input Iterator friend std::istream& operator>>(std::istream& is, CompleteLine& cl) { std::getline(is, cl.completeLine); return is; } operator std::string() const { return completeLine; } // cast operator std::string completeLine{}; }; std::istringstream iss{ R"(1 Line AAA 2 Line BBB 3 Line CCC)" }; int main() { for (const std::string& line : std::ranges::views::istream<CompleteLine>(iss) | std::views::transform([](std::string line) { std::ranges::transform(line, line.begin(), [](auto c) { return std::tolower(c); }); return line; })) { std::cout << line << '\n'; } }
编译错误信息:
s\Armin\source\repos\Stackoverflow\Stackoverflow\stackoverflow.cpp(21,56): error C2039: 'istream': is not a member of 'std::ranges::views' 1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\include\ranges(4051): message : see declaration of 'std::ranges::views' 1>C:\Users\Armin\source\repos\Stackoverflow\Stackoverflow\stackoverflow.cpp(21,64): error C2275: 'CompleteLine': illegal use of this type as an expression 1>C:\Users\Armin\source\repos\Stackoverflow\Stackoverflow\stackoverflow.cpp(10): message : see declaration of 'CompleteLine' 1>C:\Users\Armin\source\repos\Stackoverflow\Stackoverflow\stackoverflow.cpp(21,5): error C2530: 'line': references must be initialized 1>C:\Users\Armin\source\repos\Stackoverflow\Stackoverflow\stackoverflow.cpp(21,34): error C2143: syntax error: missing ';' before ':' 1>C:\Users\Armin\source\repos\Stackoverflow\Stackoverflow\stackoverflow.cpp(26,15): error C2143: syntax error: missing ';' before ')' 1>Done building project "Stackoverflow.vcxproj" -- FAILED.
使用环境:Microsoft Visual Studio Community 2019(版本16.11.9),已启用Preview - Features from the Latest C++ Working Draft (/std:c++latest)。
错误原因与修正方案
- 命名空间错误:标准中输入流视图的正确名称是
std::views::istream,而非std::ranges::views::istream,原代码使用了错误的命名空间路径。 - 编译器解析歧义:原代码把管道视图直接写在for循环的range表达式里,换行可能导致编译器解析混乱,将视图提取为单独变量即可解决。
std::tolower的未定义行为:直接传递char类型给std::tolower可能触发未定义行为(当char为有符号类型且值为负时),需要转换为unsigned char。- 缺失头文件:
std::tolower的声明在<cctype>中,原代码未包含该头文件。
修正后的完整代码
#include <iostream> #include <sstream> #include <string> #include <iterator> #include <ranges> #include <algorithm> #include <cctype> namespace rng = std::ranges; struct CompleteLine { friend std::istream& operator>>(std::istream& is, CompleteLine& cl) { std::getline(is, cl.completeLine); return is; } operator std::string() const { return completeLine; } std::string completeLine{}; }; std::istringstream iss{ R"(1 Line AAA 2 Line BBB 3 Line CCC)" }; int main() { auto line_view = std::views::istream<CompleteLine>(iss) | std::views::transform([](std::string line) { rng::transform(line, line.begin(), [](unsigned char c) { return std::tolower(c); }); return line; }); for (const std::string& line : line_view) { std::cout << line << '\n'; } }
运行结果
程序执行后会输出:
1 line aaa 2 line bbb 3 line ccc
内容的提问来源于stack exchange,提问作者A M
相关产品推荐
相关产品推荐

