Loading...
Searching...
No Matches
pairtraversal.hh
Go to the documentation of this file.
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-GPL-2.0-only-with-PDELab-exception
#ifndef DUNE_TYPETREE_PAIRTRAVERSAL_HH
#define DUNE_TYPETREE_PAIRTRAVERSAL_HH
#include <dune/common/std/type_traits.hh>
#include <dune/typetree/nodeinterface.hh>
#include <dune/typetree/nodetags.hh>
#include <dune/typetree/treepath.hh>
#include <dune/typetree/visitor.hh>
#include <dune/typetree/traversal.hh>
namespace Dune {
namespace TypeTree {
namespace Detail {
/* The signature is the same as for the public applyToTreePair
* function in Dune::Typtree, despite the additionally passed
* treePath argument. The path passed here is associated to
* the tree and the relative paths of the children (wrt. to tree)
* are appended to this. Hence the behavior of the public function
* is resembled by passing an empty treePath.
*/
/*
* This is the overload for leaf traversal
*/
template<class T1, class T2, class TreePath, class V,
std::enable_if_t<(std::decay_t<T1>::isLeaf or std::decay_t<T2>::isLeaf), int> = 0>
void applyToTreePair(T1&& tree1, T2&& tree2, TreePath treePath, V&& visitor)
{
visitor.leaf(tree1, tree2, treePath);
}
/*
* This is the general overload doing static child traversal.
*/
template<class T1, class T2, class TreePath, class V,
std::enable_if_t<not(std::decay_t<T1>::isLeaf or std::decay_t<T2>::isLeaf), int> = 0>
void applyToTreePair(T1&& tree1, T2&& tree2, TreePath treePath, V&& visitor)
{
// Do we really want to take care for const-ness of the Tree
// when instanciating VisitChild below? I'd rather expect this:
// using Tree1 = std::decay_t<T1>;
// using Tree2 = std::decay_t<T2>;
// using Visitor = std::decay_t<V>;
using Tree1 = std::remove_reference_t<T1>;
using Tree2 = std::remove_reference_t<T2>;
using Visitor = std::remove_reference_t<V>;
visitor.pre(tree1, tree2, treePath);
// check which type of traversal is supported by the trees
using allowDynamicTraversal = std::conjunction<
Dune::Std::is_detected<DynamicTraversalConcept,Tree1>,
Dune::Std::is_detected<DynamicTraversalConcept,Tree2>>;
using allowStaticTraversal = std::conjunction<
Dune::Std::is_detected<StaticTraversalConcept,Tree1>,
Dune::Std::is_detected<StaticTraversalConcept,Tree2>>;
// both trees must support either dynamic or static traversal
static_assert(allowDynamicTraversal::value || allowStaticTraversal::value);
// the visitor may specify preferred dynamic traversal
using preferDynamicTraversal = std::bool_constant<Visitor::treePathType == TreePathType::dynamic>;
// create a dynamic or static index range
auto indices = [&]{
if constexpr(preferDynamicTraversal::value && allowDynamicTraversal::value)
return Dune::range(std::size_t(tree1.degree()));
else
return Dune::range(tree1.degree());
}();
if constexpr(allowDynamicTraversal::value || allowStaticTraversal::value) {
Dune::Hybrid::forEach(indices, [&](auto i) {
auto&& child1 = tree1.child(i);
auto&& child2 = tree2.child(i);
using Child1 = std::decay_t<decltype(child1)>;
using Child2 = std::decay_t<decltype(child2)>;
visitor.beforeChild(tree1, child1, tree2, child2, treePath, i);
// This requires that visitor.in(...) can always be instantiated,
// even if there's a single child only.
if (i>0)
visitor.in(tree1, tree2, treePath);
constexpr bool visitChild = Visitor::template VisitChild<Tree1,Child1,Tree2,Child2,TreePath>::value;
if constexpr(visitChild) {
auto childTreePath = Dune::TypeTree::push_back(treePath, i);
applyToTreePair(child1, child2, childTreePath, visitor);
}
visitor.afterChild(tree1, child1, tree2, child2, treePath, i);
});
}
visitor.post(tree1, tree2, treePath);
}
} // namespace Detail
template<typename Tree1, typename Tree2, typename Visitor>
void applyToTreePair(Tree1&& tree1, Tree2&& tree2, Visitor&& visitor)
{
Detail::applyToTreePair(tree1, tree2, hybridTreePath(), visitor);
}
} // namespace TypeTree
} //namespace Dune
#endif // DUNE_TYPETREE_PAIRTRAVERSAL_HH
nodetags.hh
visitor.hh
treepath.hh
traversal.hh
nodeinterface.hh
Dune::TypeTree::applyToTreePair
void applyToTreePair(Tree1 &&tree1, Tree2 &&tree2, Visitor &&visitor)
Apply visitor to a pair of TypeTrees.
Definition pairtraversal.hh:128
Dune::TypeTree::hybridTreePath
constexpr auto hybridTreePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition treepath.hh:102
Dune
Definition accumulate_static.hh:17
Dune::TypeTree
Definition accumulate_static.hh:18
Dune::TypeTree::Detail
Definition pairtraversal.hh:25
Dune::TypeTree::Detail::applyToTreePair
void applyToTreePair(T1 &&tree1, T2 &&tree2, TreePath treePath, V &&visitor)
Definition pairtraversal.hh:40