如何根据运行时布尔条件选择std::filesystem递归/非递归目录迭代器?
根据布尔值选择目录迭代器的实现方案
问题描述
我想根据布尔值isRecursive,决定使用std::filesystem::directory_iterator或std::filesystem::recursive_directory_iterator,设想的代码如下:
some_type dirIterator = isRecursive ? std::filesystem::recursive_directory_iterator : std::filesystem::directory_iterator; for (const std::filesystem::directory_entry& entry : dirIterator(path)) { // 两个迭代器的通用代码 }
我尝试用函数指针实现,但不知道这两个迭代器的“公共”返回类型该怎么写:
??? (*dirIterator) (const std::filesystem::path & dirPath);
希望了解所有可行方案,优先选择简单的实现。
可行方案
方案一:封装通用逻辑+分支调用(最直观简单)
直接把通用处理逻辑抽成独立函数,再通过分支选择对应的遍历方式,完全不用复杂语法,新手也能快速理解:
#include <filesystem> namespace fs = std::filesystem; // 抽离通用处理逻辑 void process_entry(const fs::directory_entry& entry) { // 这里写你的通用代码,比如打印路径 std::cout << entry.path() << '\n'; } // 普通目录遍历 void traverse_simple(const fs::path& path) { for (const auto& entry : fs::directory_iterator(path)) { process_entry(entry); } } // 递归目录遍历 void traverse_recursive(const fs::path& path) { for (const auto& entry : fs::recursive_directory_iterator(path)) { process_entry(entry); } } // 调用处 if (isRecursive) { traverse_recursive(path); } else { traverse_simple(path); }
方案二:用std::variant+std::visit(C++17及以上)
利用C++17的std::variant存储两种迭代器类型,再通过std::visit统一触发遍历,代码更紧凑:
#include <filesystem> #include <variant> namespace fs = std::filesystem; // ... // 创建对应的迭代器变体 using IteratorVar = std::variant<fs::directory_iterator, fs::recursive_directory_iterator>; IteratorVar dir_iter = isRecursive ? IteratorVar(fs::recursive_directory_iterator(path)) : IteratorVar(fs::directory_iterator(path)); // 遍历变体中的迭代器 std::visit([](auto&& iter) { for (const fs::directory_entry& entry : iter) { // 通用处理逻辑 std::cout << entry.path() << '\n'; } }, dir_iter);
方案三:动态多态封装(适合复杂扩展场景)
如果需要在运行时动态切换遍历方式,或者有后续扩展更多遍历类型的需求,可以用抽象基类封装:
#include <filesystem> #include <functional> #include <memory> namespace fs = std::filesystem; // 抽象遍历器基类 class DirectoryTraverser { public: virtual ~DirectoryTraverser() = default; virtual void traverse(const std::function<void(const fs::directory_entry&)>& processor) = 0; }; // 普通遍历器实现 class SimpleTraverser : public DirectoryTraverser { public: SimpleTraverser(const fs::path& path) : iter_(path) {} void traverse(const std::function<void(const fs::directory_entry&)>& processor) override { for (const auto& entry : iter_) { processor(entry); } } private: fs::directory_iterator iter_; }; // 递归遍历器实现 class RecursiveTraverser : public DirectoryTraverser { public: RecursiveTraverser(const fs::path& path) : iter_(path) {} void traverse(const std::function<void(const fs::directory_entry&)>& processor) override { for (const auto& entry : iter_) { processor(entry); } } private: fs::recursive_directory_iterator iter_; }; // 调用处 std::unique_ptr<DirectoryTraverser> traverser; if (isRecursive) { traverser = std::make_unique<RecursiveTraverser>(path); } else { traverser = std::make_unique<SimpleTraverser>(path); } traverser->traverse([](const fs::directory_entry& entry) { // 通用处理逻辑 std::cout << entry.path() << '\n'; });
关于函数指针的补充说明
你尝试的函数指针方式不可行,因为directory_iterator和recursive_directory_iterator是完全独立的类型,它们的构造函数虽然签名类似,但返回的对象类型不同,没有共同的基类(除了std::iterator相关的空基类,但没法直接用来统一调用),因此无法用单一的函数指针类型兼容两者。
内容的提问来源于stack exchange,提问作者andre pacheco
相关产品推荐
相关产品推荐

