Skip to content

Instantly share code, notes, and snippets.

@TylerGlaiel
Last active April 29, 2025 03:39
Show Gist options
  • Save TylerGlaiel/7b6fa06628883148e4403b3cc616fdec to your computer and use it in GitHub Desktop.
Save TylerGlaiel/7b6fa06628883148e4403b3cc616fdec to your computer and use it in GitHub Desktop.
#include <vector>
#include <string>
#include <iostream>
enum class _tree_return {
Continue = 0,
Prune,
Break
};
template<typename T, typename F1, typename F2, typename F3>
_tree_return _for_tree(T initial, F1 condition, F2 branch, F3 visit) {
_tree_return result = visit(initial);
if(result == _tree_return::Break) return _tree_return::Break;
if(result != _tree_return::Prune) {
for(T subnode : branch(initial)) {
if(condition(subnode)) {
_tree_return result = _for_tree(subnode, condition, branch, visit);
if(result == _tree_return::Break) return _tree_return::Break;
}
}
}
return _tree_return::Continue;
}
#define tree_break return _tree_return::Break
#define tree_prune return _tree_return::Prune
#define tree_continue return _tree_return::Continue
//v-- semicolon to not allow you to get the return value here
#define for_tree(XName, Xinitial, Condition, Branch, Visit) ;_for_tree(Xinitial, \
[&](decltype(Xinitial) XName){ return Condition; }, \
[&](decltype(Xinitial) XName){ return std::vector<decltype(Xinitial)>Branch; }, \
[&](decltype(Xinitial) XName){ Visit; return _tree_return::Continue; })
//excuse the use of a std::vector in there, I guess you cant return an initialize_list from a lambda
//that wouldn't really be an issue if this was implemented at the language level instead of hacked together from lambdas and macros
struct Node {
Node* left = NULL;
Node* right = NULL;
std::string value;
Node(std::string value):value(value){}
};
int main() {
//syntax is a little uglier than it could be if it was native
//imperative tree sample
for_tree(x, std::string(""), x.size()<=8, ({x+"a", x+"b", x+"c"}), {
std::cout << x << std::endl;
});
//tree structure sample
Node mytree("root");
mytree.left = new Node("left");
mytree.right = new Node("right");
mytree.left->left = new Node("leftleft");
for_tree(x, &mytree, x != NULL, ({x->left, x->right}), {
std::cout << x->value << std::endl;
});
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment