boost::adaptors::transformed与std::filesystem::directory_iterator异常问题
问题分析与解决
你的问题确实是std::filesystem::directory_iterator的单遍迭代特性导致的:
- 这个迭代器属于单遍输入迭代器,只能完整遍历一次,遍历完成后迭代器会处于结束状态,无法重置回起始位置。
- 你定义的
names是惰性求值的Boost Range适配器链,它并没有提前存储目录元素,每次调用boost::size或遍历它时,都会基于持有的迭代器执行遍历操作。第一次调用boost::size时,迭代器已经被推进到结束位置;第二次调用时,起始迭代器已经等于结束迭代器,自然会得到错误的结果。
解决方案:将惰性序列转为容器存储
把惰性求值的Range转换成实际的容器(比如std::vector),一次性提取并保存所有结果,这样后续可以多次访问而不会受限于迭代器的单遍特性:
#include <boost/range/adaptors.hpp> #include <boost/static_string/static_string.hpp> #include <boost/utility/string_view.hpp> #include <filesystem> #include <iostream> #include <vector> // 新增头文件 const auto root = std::filesystem::path("."); // 使用boost::copy_range将结果存入vector const auto names = boost::copy_range<std::vector<boost::static_string<64>>>( boost::make_iterator_range( std::filesystem::directory_iterator(root), std::filesystem::directory_iterator {} ) | boost::adaptors::filtered([](const std::filesystem::directory_entry& entry) { const auto name = entry.path().stem().string(); const auto suff = entry.path().extension().string(); return suff == ".cfg" && !boost::string_view(name).starts_with("__"); }) | boost::adaptors::transformed([](const std::filesystem::directory_entry& entry) { auto result = boost::static_string<64>{}; result = entry.path().stem().string(); std::cout << result << std::endl; return result; }) ); // 现在多次调用size都会返回正确结果 std::cout << boost::size(names) << std::endl; std::cout << boost::size(names) << std::endl;
额外说明
如果不想提前存储所有元素,也可以每次需要遍历的时候重新构造directory_iterator和Range链,但这种方式每次都会重新扫描目录,性能上不如提前存入容器高效。
内容的提问来源于stack exchange,提问作者Edward Sarkisyan
相关产品推荐
相关产品推荐

