如何在C++20/C++23中链式调用视图实现元素打印?
关于std::ranges视图链式打印的问题
核心结论
没错,C++标准库中确实不存在std::views::for_each。
为什么你的尝试没生效?
views::transform做打印无效:
视图的核心特性是惰性求值——只有当视图被实际迭代(比如遍历、转成容器)时,转换逻辑才会执行。你用transform嵌入打印逻辑,但如果没有触发迭代,lambda里的代码根本不会运行。而且从设计角度讲,transform应该用于无副作用的转换操作,把打印这种副作用放在这里也不符合视图的设计意图。views::join用法错误:join的作用是扁平化嵌套范围(比如把std::vector<std::vector<int>>转换成单层的int范围),和字符串打印完全不相关,自然无法达到目的。
实现链式打印的可行方案
方案1:自定义链式适配器
可以自己实现一个适配符,让for_each能通过|链式调用:
#include <chrono> #include <iostream> #include <ranges> #include <algorithm> using namespace std; namespace c = std::chrono; namespace v = std::views; namespace r = std::ranges; // 自定义链式for_each适配器 struct for_each_adaptor { template<typename Func> auto operator()(Func&& func) const { return [func = std::forward<Func>(func)](auto&& range) { r::for_each(std::forward<decltype(range)>(range), func); return std::forward<decltype(range)>(range); // 可选:返回原范围支持后续链式操作 }; } }; inline constexpr for_each_adaptor for_each; int main() { auto show_name = [](const string_view name) { cout << name << ' '; }; const auto& db = c::get_tzdb(); db.zones | v::transform([](const c::time_zone& z) { return z.name(); }) | v::filter([](const string_view name) { return name.starts_with("Europe/Be"); }) | for_each(show_name); cout << " <- Europe/Be*\n"; }
这个适配器接收一个函数对象,返回的lambda会接收范围并调用ranges::for_each执行副作用,还可以返回原范围让你继续链式调用其他视图操作。
方案2:直接将范围表达式传入ranges::for_each
如果不需要严格的视图链式写法,可以直接把转换后的范围作为ranges::for_each的第一个参数,代码同样紧凑:
#include <chrono> #include <iostream> #include <ranges> #include <algorithm> using namespace std; namespace c = std::chrono; namespace v = std::views; namespace r = std::ranges; int main() { auto show_name = [](const string_view name) { cout << name << ' '; }; const auto& db = c::get_tzdb(); r::for_each( db.zones | v::transform([](const c::time_zone& z) { return z.name(); }) | v::filter([](const string_view name) { return name.starts_with("Europe/Be"); }), show_name ); cout << " <- Europe/Be*\n"; }
额外说明
标准库把ranges::for_each归为算法而非视图适配器,是因为视图的职责是描述数据的转换逻辑(无副作用),而for_each是触发执行并产生副作用的操作,两者的设计定位不同。
内容的提问来源于stack exchange,提问作者towi
相关产品推荐
相关产品推荐

