Last active
August 15, 2019 20:43
-
-
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.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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