C++23stlexpert
std::filesystem::recursive_directory_iterator Improvements (C++23 Evolution)
C++23 · Completing Modern · Compiler flag: -std=c++23
Explanation
Enhanced performance and usability for recursive directory iteration.
Real-World Scenario
Traverse a directory tree efficiently in a file explorer.
Quick Snippet
snippet.cpp
#include <filesystem> for (auto& p : std::filesystem::recursive_directory_iterator("dir")) {}Full Example
filesystem_recursive.cpp
// CodeNebula - C++23 Example: filesystem::recursive_directory_iterator Improvements
// Compile: g++ -std=c++23 -Wall -Wextra -o example filesystem_recursive.cpp
// Note: Requires GCC 13+ / Clang 17+
#include <filesystem>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
namespace fs = std::filesystem;
// C++23 continues to refine <filesystem>. This example demonstrates
// recursive_directory_iterator with improved error handling,
// directory_options, and integration with C++23 ranges.
void print_tree(const fs::path& root, int max_depth = 3) {
std::error_code ec;
auto options = fs::directory_options::skip_permission_denied;
auto it = fs::recursive_directory_iterator(root, options, ec);
if (ec) {
std::cout << "Error opening " << root << ": " << ec.message() << "\n";
return;
}
for (const auto& entry : it) {
if (it.depth() > max_depth) {
it.disable_recursion_pending();
continue;
}
std::string indent(it.depth() * 2, ' ');
if (entry.is_directory(ec)) {
std::cout << indent << "[DIR] " << entry.path().filename().string() << "/\n";
} else if (entry.is_regular_file(ec)) {
auto size = entry.file_size(ec);
std::cout << indent << "[FILE] " << entry.path().filename().string()
<< " (" << (ec ? 0 : size) << " bytes)\n";
}
}
}
int main() {
std::cout << "=== filesystem::recursive_directory_iterator improvements ===\n\n";
// Create a temporary directory structure for demonstration
auto temp = fs::temp_directory_path() / "codenebula_fs_demo";
fs::remove_all(temp); // Clean up previous run
fs::create_directories(temp / "src" / "core");
fs::create_directories(temp / "src" / "utils");
fs::create_directories(temp / "docs");
// Create some files
for (auto name : {"main.cpp", "README.md"}) {
std::ofstream(temp / name) << "// " << name << "\n";
}
for (auto name : {"engine.cpp", "engine.h"}) {
std::ofstream(temp / "src" / "core" / name) << "// " << name << "\n";
}
std::ofstream(temp / "src" / "utils" / "helpers.h") << "// helpers\n";
std::ofstream(temp / "docs" / "guide.md") << "# Guide\n";
// Print directory tree
std::cout << "Directory tree of " << temp.filename().string() << "/:\n";
print_tree(temp);
// Collect all .cpp files recursively
std::cout << "\n--- All .cpp files ---\n";
std::vector<fs::path> cpp_files;
for (const auto& entry : fs::recursive_directory_iterator(temp)) {
if (entry.is_regular_file() && entry.path().extension() == ".cpp") {
cpp_files.push_back(entry.path());
}
}
std::ranges::sort(cpp_files);
for (const auto& p : cpp_files) {
std::cout << " " << fs::relative(p, temp).string() << "\n";
}
// Count entries by type
std::cout << "\n--- Statistics ---\n";
int dirs = 0, files = 0;
for (const auto& entry : fs::recursive_directory_iterator(temp)) {
if (entry.is_directory()) ++dirs;
else if (entry.is_regular_file()) ++files;
}
std::cout << "Directories: " << dirs << "\n";
std::cout << "Files: " << files << "\n";
// Cleanup
fs::remove_all(temp);
std::cout << "\nTemporary directory cleaned up.\n";
return 0;
}
// Expected output (paths may vary):
// === filesystem::recursive_directory_iterator improvements ===
//
// Directory tree of codenebula_fs_demo/:
// [DIR] docs/
// [FILE] guide.md (8 bytes)
// [DIR] src/
// [DIR] core/
// [FILE] engine.cpp (15 bytes)
// [FILE] engine.h (14 bytes)
// [DIR] utils/
// [FILE] helpers.h (11 bytes)
// [FILE] main.cpp (13 bytes)
// [FILE] README.md (14 bytes)
//
// --- All .cpp files ---
// main.cpp
// src/core/engine.cpp
//
// --- Statistics ---
// Directories: 4
// Files: 5
//
// Temporary directory cleaned up.
Run command
g++ -std=c++23 -Wall -Wextra -o example filesystem_recursive.cpp