You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 02:25:46