DUNE PDELab (2.7)

treecontainer.hh
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3
4#ifndef DUNE_TYPETREE_TREECONTAINER_HH
5#define DUNE_TYPETREE_TREECONTAINER_HH
6
7#include <type_traits>
8#include <utility>
9#include <functional>
10#include <array>
11
12#include <dune/common/indices.hh>
14
15#include <dune/typetree/treepath.hh>
16
17namespace Dune {
18 namespace TypeTree {
19
20 namespace Detail {
21
22 /*
23 * \brief A factory class creating a hybrid container compatible with a type tree
24 *
25 * This class allows to create a nested hybrid container having the same structure
26 * as a given type tree. Power nodes are represented as std::array's while composite
27 * nodes are represented as Dune::TupleVector's. The stored values for the leaf nodes
28 * are creating using a given predicate. Once created, the factory provides an
29 * operator() creating the container for the tree given as argument.
30 *
31 * \tparam LeafToValue Type of a predicate that determines the stored values at the leafs
32 */
33 template<class LeafToValue>
34 class ContainerFactory
35 {
36 public:
37
45 ContainerFactory(LeafToValue leafToValue) :
46 leafToValue_(leafToValue)
47 {}
48
49 template<class Node,
50 std::enable_if_t<Node::isLeaf, int> = 0>
51 auto operator()(const Node& node)
52 {
53 return leafToValue_(node);
54 }
55
56 template<class Node,
57 std::enable_if_t<Node::isPower, int> = 0>
58 auto operator()(const Node& node)
59 {
60 using TransformedChild = decltype((*this)(node.child(0)));
61 return std::array<TransformedChild, Node::degree()>();
62 }
63
64 template<class Node,
65 std::enable_if_t<Node::isComposite, int> = 0>
66 auto operator()(const Node& node)
67 {
68 return Dune::unpackIntegerSequence([&](auto... indices) {
69 return Dune::makeTupleVector((*this)(node.child(indices))...);
70 }, std::make_index_sequence<Node::degree()>());
71 }
72
73 private:
74 LeafToValue leafToValue_;
75 };
76
77
78 /*
79 * \brief Wrap nested container to provide a VectorBackend
80 */
81 template<class Container>
82 class TreeContainerVectorBackend
83 {
84 template<class C>
85 static constexpr decltype(auto) accessByTreePath(C&& container, const HybridTreePath<>& path)
86 {
87 return container;
88 }
89
90 template<class C, class... T>
91 static constexpr decltype(auto) accessByTreePath(C&& container, const HybridTreePath<T...>& path)
92 {
93 auto head = path[Dune::Indices::_0];
94 auto tailPath = Dune::unpackIntegerSequence([&](auto... i){
95 return treePath(path[i+1]...);
96 }, std::make_index_sequence<sizeof...(T)-1>());
97 return accessByTreePath(container[head], tailPath);
98 }
99
100 public:
101 TreeContainerVectorBackend() :
102 container_()
103 {}
104
105 TreeContainerVectorBackend(Container&& container) :
106 container_(std::move(container))
107 {}
108
109 TreeContainerVectorBackend(TreeContainerVectorBackend&& other) :
110 container_(std::move(other.container_))
111 {}
112
113 template<class... T>
114 decltype(auto) operator[](const HybridTreePath<T...>& path) const
115 {
116 return accessByTreePath(container_, path);
117 }
118
119 template<class... T>
120 decltype(auto) operator[](const HybridTreePath<T...>& path)
121 {
122 return accessByTreePath(container_, path);
123 }
124
125 const Container& data() const
126 {
127 return container_;
128 }
129
130 Container& data()
131 {
132 return container_;
133 }
134
135 private:
136 Container container_;
137 };
138
139 template<class Container>
140 auto makeTreeContainerVectorBackend(Container&& container)
141 {
142 return TreeContainerVectorBackend<std::decay_t<Container>>(std::forward<Container>(container));
143 }
144
145 /*
146 * \brief A simple lambda for creating default constructible values from a node
147 *
148 * This simply returns LeafToValue<Node>{} for a given Node. It's needed
149 * because using a lambda expression in a using declaration is not allowed
150 * because it's an unevaluated context.
151 */
152 template<template<class Node> class LeafToValue>
153 struct LeafToDefaultConstructibleValue
154 {
155 template<class Node>
156 auto operator()(const Node& node) const
157 {
158 return LeafToValue<Node>{};
159 }
160 };
161
162 } // namespace Detail
163
183 template<class Tree, class LeafToValue>
184 auto makeTreeContainer(const Tree& tree, LeafToValue&& leafToValue)
185 {
186 auto f = std::ref(leafToValue);
187 auto factory = Detail::ContainerFactory<decltype(f)>(f);
188 return Detail::makeTreeContainerVectorBackend(factory(tree));
189 }
190
206 template<class Value, class Tree>
207 auto makeTreeContainer(const Tree& tree)
208 {
209 return makeTreeContainer(tree, [](const auto&) {return Value{};});
210 }
211
215 template<class Value, class Tree>
216 using UniformTreeContainer = std::decay_t<decltype(makeTreeContainer<Value>(std::declval<const Tree&>()))>;
217
221 template<template<class Node> class LeafToValue, class Tree>
222 using TreeContainer = std::decay_t<decltype(makeTreeContainer(std::declval<const Tree&>(), std::declval<Detail::LeafToDefaultConstructibleValue<LeafToValue>>()))>;
223
225
226 } // namespace TypeTree
227} //namespace Dune
228
229#endif // DUNE_TYPETREE_TREECONTAINER_HH
decltype(auto) unpackIntegerSequence(F &&f, std::integer_sequence< I, i... > sequence)
Unpack an std::integer_sequence<I,i...> to std::integral_constant<I,i>...
Definition: indices.hh:123
constexpr index_constant< 0 > _0
Compile time index with value 0.
Definition: indices.hh:51
constexpr HybridTreePath< T... > treePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:188
std::decay_t< decltype(makeTreeContainer< Value >(std::declval< const Tree & >()))> UniformTreeContainer
Alias to container type generated by makeTreeContainer for given tree type and uniform value type.
Definition: treecontainer.hh:216
std::decay_t< decltype(makeTreeContainer(std::declval< const Tree & >(), std::declval< Detail::LeafToDefaultConstructibleValue< LeafToValue > >()))> TreeContainer
Alias to container type generated by makeTreeContainer for give tree type and when using LeafToValue ...
Definition: treecontainer.hh:222
auto makeTreeContainer(const Tree &tree)
Create container havin the same structure as the given tree.
Definition: treecontainer.hh:207
Dune namespace.
Definition: alignedallocator.hh:14
STL namespace.
Provides the TupleVector class that augments std::tuple by operator[].
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)