Commit f5f52edc authored by Carsten Gräser's avatar Carsten Gräser Committed by Steffen Müthing

Add tree traversal with callbacks

This simplifies traversing trees in many cases because one can
write classic "loops" by using lambdas as callbacks, e.g.,

  int i=0;
  forEachNode(tree, [](auto&&...) {
    ++i;
  });

Notice that there is no need to use std::forward() in the new functions:
Neither the tree nor the callbacks are stored by value. Hence there
is no need to forward them as r-value references. Instead the CallbackVisitor
stores references to functions. This is OK, because it does not outlive
the forEach*() call such that it's safe to pass temporaries.
parent f78f852b
......@@ -161,6 +161,51 @@ namespace Dune {
#endif // DOXYGEN
namespace Detail {
template<class PreFunc, class LeafFunc, class PostFunc>
struct CallbackVisitor :
public TypeTree::TreeVisitor,
public TypeTree::DynamicTraversal
{
public:
CallbackVisitor(PreFunc& preFunc, LeafFunc& leafFunc, PostFunc& postFunc) :
preFunc_(preFunc),
leafFunc_(leafFunc),
postFunc_(postFunc)
{}
template<typename Node, typename TreePath>
void pre(Node&& node, TreePath treePath)
{
preFunc_(node, treePath);
}
template<typename Node, typename TreePath>
void leaf(Node&& node, TreePath treePath)
{
leafFunc_(node, treePath);
}
template<typename Node, typename TreePath>
void post(Node&& node, TreePath treePath)
{
postFunc_(node, treePath);
}
private:
PreFunc& preFunc_;
LeafFunc& leafFunc_;
PostFunc& postFunc_;
};
template<class PreFunc, class LeafFunc, class PostFunc>
auto callbackVisitor(PreFunc& preFunc, LeafFunc& leafFunc, PostFunc& postFunc)
{
return CallbackVisitor<PreFunc, LeafFunc, PostFunc>(preFunc, leafFunc, postFunc);
}
} // namespace Detail
// ********************************************************************************
......@@ -189,6 +234,71 @@ namespace Dune {
std::forward<Visitor>(visitor));
}
/**
* \brief Traverse tree and visit each node
*
* All passed callback functions are called with the
* node and corresponding treepath as arguments.
*
* \param tree The tree to traverse
* \param preFunc This function is called for each inner node before visiting its children
* \param leafFunc This function is called for each leaf node
* \param postFunc This function is called for each inner node after visiting its children
*/
template<class Tree, class PreFunc, class LeafFunc, class PostFunc>
auto forEachNode(Tree&& tree, PreFunc&& preFunc, LeafFunc&& leafFunc, PostFunc&& postFunc)
{
applyToTree(tree, Detail::callbackVisitor(preFunc, leafFunc, postFunc));
}
/**
* \brief Traverse tree and visit each node
*
* All passed callback functions are called with the
* node and corresponding treepath as arguments.
*
* \param tree The tree to traverse
* \param innerFunc This function is called for each inner node before visiting its children
* \param leafFunc This function is called for each leaf node
*/
template<class Tree, class InnerFunc, class LeafFunc>
auto forEachNode(Tree&& tree, InnerFunc&& innerFunc, LeafFunc&& leafFunc)
{
auto nop = [](auto&&... args) {};
forEachNode(tree, innerFunc, leafFunc, nop);
}
/**
* \brief Traverse tree and visit each node
*
* The passed callback function is called with the
* node and corresponding treepath as arguments.
*
* \param tree The tree to traverse
* \param nodeFunc This function is called for each node
*/
template<class Tree, class NodeFunc>
auto forEachNode(Tree&& tree, NodeFunc&& nodeFunc)
{
forEachNode(tree, nodeFunc, nodeFunc);
}
/**
* \brief Traverse tree and visit each leaf node
*
* The passed callback function is called with the
* node and corresponding treepath as arguments.
*
* \param tree The tree to traverse
* \param leafFunc This function is called for each leaf node
*/
template<class Tree, class LeafFunc>
auto forEachLeafNode(Tree&& tree, LeafFunc&& leafFunc)
{
auto nop = [](auto&&... args) {};
forEachNode(tree, nop, leafFunc, nop);
}
//! \} group Tree Traversal
} // namespace TypeTree
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment