如何将std::views::lazy_split拆分的wcin输入token转为std::wstring?
如何将std::views::lazy_split的结果转换为std::wstring?
问题描述
尝试借助C++标准库从std::wcin提取并遍历token,代码如下:
auto input = std::views::istream<wchar_t>(std::wcin); auto tokens = input | std::views::lazy_split(L' '); for (auto const& token : tokens) { std::wstring s1(token); // 无法编译 std::wstring s; s = token; // 无法编译 s = std::wstring(token); // 无法编译 s = std::wstring{token.begin(), token.end()}; // 无法编译 s = std::wstring(token.begin(), token.end()); // 无法编译 s = std::wstring(token.cbegin(), token.cend()); // 无法编译 // 需要将token转为字符串后执行操作 do_something_with_the_token_string(s); }
编译失败,token的类型为std::ranges::lazy_split_view<std::ranges::basic_istream_view<wchar_t,_Elem,_Traits>,std::ranges::single_view<wchar_t>>::_Outer_iter<false>::value_type,使用Visual Studio 17.9.1,编译选项/std:c++20。
解决方案
问题核心在于lazy_split返回的每个token是输入范围(input range),其迭代器属于input_iterator范畴,而std::wstring的构造函数要求迭代器至少是前向迭代器(forward iterator),因此直接调用构造函数无法通过编译。
C++20 兼容方案
使用std::ranges::copy配合std::back_inserter,将token中的字符逐个复制到std::wstring中:
#include <algorithm> #include <ranges> #include <string> #include <iostream> void do_something_with_the_token_string(const std::wstring& s) { // 示例操作 std::wcout << L"Token: " << s << std::endl; } int main() { auto input = std::views::istream<wchar_t>(std::wcin); auto tokens = input | std::views::lazy_split(L' '); for (auto const& token : tokens) { std::wstring s; std::ranges::copy(token, std::back_inserter(s)); do_something_with_the_token_string(s); } return 0; }
若可升级到C++23
C++23引入了std::ranges::to,可以直接将范围转换为容器,代码更简洁:
for (auto const& token : tokens) { std::wstring s = std::ranges::to<std::wstring>(token); do_something_with_the_token_string(s); }
额外说明
std::views::istream是输入范围,迭代器仅支持单向遍历且不可重复使用,因此lazy_split生成的子范围也继承了这一特性,无法满足std::wstring构造函数对迭代器的要求。std::back_inserter会自动扩展std::wstring的容量,适配token的实际长度。
内容的提问来源于stack exchange,提问作者h.s.
相关产品推荐
相关产品推荐

