Skip to content

Instantly share code, notes, and snippets.

@christianparpart
Last active August 15, 2019 20:43
Show Gist options
  • Select an option

  • Save christianparpart/7b88862d94946a0ee79a1dc50e20a323 to your computer and use it in GitHub Desktop.

Select an option

Save christianparpart/7b88862d94946a0ee79a1dc50e20a323 to your computer and use it in GitHub Desktop.
A small example on how you could code more functional-style in C++ 17/14/11.
// C++17 version of some code shown here in Java:
// https://github.com/impulse-cl/impulse/blob/master/src/main/java/io/impulsecloud/daemon/blueprint/indexer/FileSystemBlueprintIndexer.java#L42
// Since C++ does not provide the convinient API we just implemented it ourselves.
//
// How to compile:
// g++ -std=c++17 demo.cpp -o demo -lstdc++fs
//
// NOTE: This is just for showing what is possible, not for providing the best-possible speed optimized and feature-complete solution.
#include <iostream>
#include <experimental/filesystem>
#include <functional>
#include <algorithm>
#include <string>
#include <vector>
#include <stack>
using namespace std;
namespace fs = std::experimental::filesystem;
class Files { // {{{
public:
using PathCheck = std::function<bool(const fs::path&)>;
using PathCallback = std::function<void(const fs::path&)>;
static Files walk(const fs::path& root, size_t depth)
{
Files aux;
_walkThis(root, depth, 0, &aux.files);
return move(aux);
}
Files filter(PathCheck check)
{
Files aux;
copy_if(begin(aux.files), end(aux.files), back_inserter(aux.files), check);
return move(aux);
}
void forEach(PathCallback callback)
{
for_each(begin(files), end(files), callback);
}
private:
static void _walkThis(const fs::path& root, size_t depth, size_t currentDepth, vector<fs::path>* aux)
{
if (currentDepth < depth)
for (const fs::path& p : fs::directory_iterator(root))
{
aux->push_back(p);
if (fs::is_directory(p))
_walkThis(p, depth, currentDepth + 1, aux);
}
}
vector<fs::path> files;
};
// }}}
int main(int argc, const char* argv[])
{
const string directory = argc > 1 ? argv[1] : "/etc";
const size_t depth = 5;
try
{
Files::walk(directory, depth)
.filter([](auto path) { return fs::is_directory(path); })
.forEach([](auto path) { cout << path << '\n'; });
}
catch (const exception& e)
{
cerr << "some error happened: " << e.what() << '\n';
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
// vim:ts=4:sw=4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment