DUNE PDELab (git)

pairtraversal.hh
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-GPL-2.0-only-with-PDELab-exception
5
6#ifndef DUNE_TYPETREE_PAIRTRAVERSAL_HH
7#define DUNE_TYPETREE_PAIRTRAVERSAL_HH
8
9#include <dune/common/std/type_traits.hh>
10
11#include <dune/typetree/nodeinterface.hh>
12#include <dune/typetree/nodetags.hh>
13#include <dune/typetree/treepath.hh>
14#include <dune/typetree/visitor.hh>
15#include <dune/typetree/traversal.hh>
16
17namespace Dune {
18 namespace TypeTree {
19
25 namespace Detail {
26
27 /* The signature is the same as for the public applyToTreePair
28 * function in Dune::Typtree, despite the additionally passed
29 * treePath argument. The path passed here is associated to
30 * the tree and the relative paths of the children (wrt. to tree)
31 * are appended to this. Hence the behavior of the public function
32 * is resembled by passing an empty treePath.
33 */
34
35 /*
36 * This is the overload for leaf traversal
37 */
38 template<class T1, class T2, class TreePath, class V,
39 std::enable_if_t<(std::decay_t<T1>::isLeaf or std::decay_t<T2>::isLeaf), int> = 0>
40 void applyToTreePair(T1&& tree1, T2&& tree2, TreePath treePath, V&& visitor)
41 {
42 visitor.leaf(tree1, tree2, treePath);
43 }
44
45 /*
46 * This is the general overload doing static child traversal.
47 */
48 template<class T1, class T2, class TreePath, class V,
49 std::enable_if_t<not(std::decay_t<T1>::isLeaf or std::decay_t<T2>::isLeaf), int> = 0>
50 void applyToTreePair(T1&& tree1, T2&& tree2, TreePath treePath, V&& visitor)
51 {
52 // Do we really want to take care for const-ness of the Tree
53 // when instanciating VisitChild below? I'd rather expect this:
54 // using Tree1 = std::decay_t<T1>;
55 // using Tree2 = std::decay_t<T2>;
56 // using Visitor = std::decay_t<V>;
57 using Tree1 = std::remove_reference_t<T1>;
58 using Tree2 = std::remove_reference_t<T2>;
59 using Visitor = std::remove_reference_t<V>;
60 visitor.pre(tree1, tree2, treePath);
61
62 // check which type of traversal is supported by the trees
63 using allowDynamicTraversal = std::conjunction<
66 using allowStaticTraversal = std::conjunction<
69
70 // both trees must support either dynamic or static traversal
71 static_assert(allowDynamicTraversal::value || allowStaticTraversal::value);
72
73 // the visitor may specify preferred dynamic traversal
74 using preferDynamicTraversal = std::bool_constant<Visitor::treePathType == TreePathType::dynamic>;
75
76 // create a dynamic or static index range
77 auto indices = [&]{
78 if constexpr(preferDynamicTraversal::value && allowDynamicTraversal::value)
79 return Dune::range(std::size_t(tree1.degree()));
80 else
81 return Dune::range(tree1.degree());
82 }();
83
84 if constexpr(allowDynamicTraversal::value || allowStaticTraversal::value) {
85 Dune::Hybrid::forEach(indices, [&](auto i) {
86 auto&& child1 = tree1.child(i);
87 auto&& child2 = tree2.child(i);
88 using Child1 = std::decay_t<decltype(child1)>;
89 using Child2 = std::decay_t<decltype(child2)>;
90
91 visitor.beforeChild(tree1, child1, tree2, child2, treePath, i);
92
93 // This requires that visitor.in(...) can always be instantiated,
94 // even if there's a single child only.
95 if (i>0)
96 visitor.in(tree1, tree2, treePath);
97
98 constexpr bool visitChild = Visitor::template VisitChild<Tree1,Child1,Tree2,Child2,TreePath>::value;
99 if constexpr(visitChild) {
100 auto childTreePath = Dune::TypeTree::push_back(treePath, i);
101 applyToTreePair(child1, child2, childTreePath, visitor);
102 }
103
104 visitor.afterChild(tree1, child1, tree2, child2, treePath, i);
105 });
106 }
107 visitor.post(tree1, tree2, treePath);
108 }
109
110 } // namespace Detail
111
113
127 template<typename Tree1, typename Tree2, typename Visitor>
128 void applyToTreePair(Tree1&& tree1, Tree2&& tree2, Visitor&& visitor)
129 {
130 Detail::applyToTreePair(tree1, tree2, hybridTreePath(), visitor);
131 }
132
134
135 } // namespace TypeTree
136} //namespace Dune
137
138#endif // DUNE_TYPETREE_PAIRTRAVERSAL_HH
typename detected_or< nonesuch, Op, Args... >::value_t is_detected
Detects whether Op<Args...> is valid.
Definition: type_traits.hh:145
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:256
constexpr HybridTreePath< T..., std::size_t > push_back(const HybridTreePath< T... > &tp, std::size_t i)
Appends a run time index to a HybridTreePath.
Definition: treepath.hh:416
constexpr auto hybridTreePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:312
constexpr auto treePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:326
void applyToTreePair(Tree1 &&tree1, Tree2 &&tree2, Visitor &&visitor)
Apply visitor to a pair of TypeTrees.
Definition: pairtraversal.hh:128
Dune namespace.
Definition: alignedallocator.hh:13
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Nov 12, 23:30, 2024)