Dune Core Modules (unstable)

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// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
4// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception OR LGPL-3.0-or-later
5
6#ifndef DUNE_COMMON_TYPETREE_TREECONTAINER_HH
7#define DUNE_COMMON_TYPETREE_TREECONTAINER_HH
8
9#include <type_traits>
10#include <utility>
11#include <functional>
12#include <array>
13
14#include <dune/common/indices.hh>
15#include <dune/common/hybridutilities.hh>
18
19#include <dune/common/typetree/nodeconcepts.hh>
20#include <dune/common/typetree/treepath.hh>
21
22namespace Dune::TypeTree {
23
24 namespace Impl {
25
37 template<class LeafToValue>
38 class ContainerFactory
39 {
40 public:
41
49 ContainerFactory(LeafToValue leafToValue) :
50 leafToValue_(leafToValue)
51 {}
52
53 template<class Node>
55 auto operator()(const Node& node)
56 {
58 return leafToValue_(node);
59 else
60 {
62 {
64 {
65 return Dune::unpackIntegerSequence([&](auto... indices) {
66 return std::array{(*this)(node.child(indices))...};
67 }, std::make_index_sequence<std::size_t(Node::degree())>());
68 }
69 else
70 {
71 using TransformedChild = decltype((*this)(node.child(0)));
72 std::vector<TransformedChild> container;
73 container.reserve(node.degree());
74 for (std::size_t i = 0; i < node.degree(); ++i)
75 container.emplace_back((*this)(node.child(i)));
76 return container;
77 }
78 }
79 else
80 {
81 return Dune::unpackIntegerSequence([&](auto... indices) {
82 return Dune::makeTupleVector((*this)(node.child(indices))...);
83 }, std::make_index_sequence<std::size_t(Node::degree())>());
84 }
85 }
86 }
87
88 private:
89 LeafToValue leafToValue_;
90 };
91
92
93 /*
94 * \brief Wrap nested container to provide a VectorBackend
95 */
96 template<class Container>
97 class TreeContainerVectorBackend
98 {
99 template<class C>
100 static constexpr decltype(auto) accessByTreePath(C&& container, const TreePath<>& path)
101 {
102 return container;
103 }
104
105 template<class C, class... T>
106 static constexpr decltype(auto) accessByTreePath(C&& container, const TreePath<T...>& path)
107 {
108 auto head = path[Dune::Indices::_0];
109 auto tailPath = Dune::unpackIntegerSequence([&](auto... i){
110 return treePath(path[Dune::index_constant<i+1>{}]...);
111 }, std::make_index_sequence<sizeof...(T)-1>());
112 return accessByTreePath(container[head], tailPath);
113 }
114
115
116 template<class C, class Tree>
117 static void recursiveResize(C& container, const Tree& tree)
118 {
120 {
121 if constexpr (requires { container.resize(0u); })
122 container.resize(tree.degree());
123 Dune::Hybrid::forEach(Dune::range(tree.degree()), [&](auto i) {
124 recursiveResize(container[i], tree.child(i));
125 });
126 }
127 }
128
129 public:
131 TreeContainerVectorBackend(Container&& container) :
132 container_(std::move(container))
133 {}
134
136 template <class Tree>
138 TreeContainerVectorBackend(const Tree& tree) :
139 TreeContainerVectorBackend()
140 {
141 this->resize(tree);
142 }
143
145 template <class C = Container,
146 std::enable_if_t<std::is_default_constructible_v<C>, bool> = true>
147 TreeContainerVectorBackend() :
148 container_()
149 {}
150
151 template<class... T>
152 decltype(auto) operator[](const TreePath<T...>& path) const
153 {
154 return accessByTreePath(container_, path);
155 }
156
157 template<class... T>
158 decltype(auto) operator[](const TreePath<T...>& path)
159 {
160 return accessByTreePath(container_, path);
161 }
162
164 template<class Tree>
166 void resize(const Tree& tree)
167 {
168 recursiveResize(container_, tree);
169 }
170
171 const Container& data() const
172 {
173 return container_;
174 }
175
176 Container& data()
177 {
178 return container_;
179 }
180
181 private:
182 Container container_;
183 };
184
185 template<class Container>
186 auto makeTreeContainerVectorBackend(Container&& container)
187 {
188 return TreeContainerVectorBackend<std::decay_t<Container>>(std::forward<Container>(container));
189 }
190
191 /*
192 * \brief A simple lambda for creating default constructible values from a node
193 *
194 * This simply returns LeafToValue<Node>{} for a given Node. It's needed
195 * because using a lambda expression in a using declaration is not allowed
196 * because it's an unevaluated context.
197 */
198 template<template<class Node> class LeafToValue>
199 struct LeafToDefaultConstructibleValue
200 {
201 template<class Node>
202 auto operator()(const Node& node) const
203 {
204 return LeafToValue<Node>{};
205 }
206 };
207
208 } // namespace Impl
209
229 template<class Tree, class LeafToValue>
230 auto makeTreeContainer(const Tree& tree, LeafToValue&& leafToValue)
231 {
232 auto f = std::ref(leafToValue);
233 auto factory = Impl::ContainerFactory<decltype(f)>(f);
234 return Impl::makeTreeContainerVectorBackend(factory(tree));
235 }
236
252 template<class Value, class Tree>
253 auto makeTreeContainer(const Tree& tree)
254 {
255 return makeTreeContainer(tree, [](const auto&) {return Value{};});
256 }
257
261 template<class Value, class Tree>
262 using UniformTreeContainer = std::decay_t<decltype(makeTreeContainer<Value>(std::declval<const Tree&>()))>;
263
267 template<template<class Node> class LeafToValue, class Tree>
268 using TreeContainer = std::decay_t<decltype(makeTreeContainer(std::declval<const Tree&>(), std::declval<Impl::LeafToDefaultConstructibleValue<LeafToValue>>()))>;
269
271
272} //namespace Dune::TypeTree
273
274#endif // DUNE_COMMON_TYPETREE_TREECONTAINER_HH
Model of a leaf tree node of a typetree.
Definition: nodeconcepts.hh:63
Model of an inner node of a typetree with compile time known degree and child access via index_consta...
Definition: nodeconcepts.hh:41
Model of a node of a typetree.
Definition: nodeconcepts.hh:34
Model of an inner node of a typetree with uniform nodes accessible via runtime index.
Definition: nodeconcepts.hh:52
constexpr index_constant< 0 > _0
Compile time index with value 0.
Definition: indices.hh:52
decltype(auto) constexpr 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:124
std::integral_constant< std::size_t, i > index_constant
An index constant with value i.
Definition: indices.hh:29
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:261
static constexpr IntegralRange< std::decay_t< T > > range(T &&from, U &&to) noexcept
free standing function for setting up a range based for loop over an integer range for (auto i: range...
Definition: rangeutilities.hh:288
constexpr auto treePath(const T &... t)
Constructs a new TreePath from the given indices.
Definition: treepath.hh:55
std::decay_t< decltype(makeTreeContainer(std::declval< const Tree & >(), std::declval< Impl::LeafToDefaultConstructibleValue< LeafToValue > >()))> TreeContainer
Alias to container type generated by makeTreeContainer for give tree type and when using LeafToValue ...
Definition: treecontainer.hh:268
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:262
auto makeTreeContainer(const Tree &tree)
Create container having the same structure as the given tree.
Definition: treecontainer.hh:253
constexpr std::integral_constant< T, I0 > head(std::integer_sequence< T, I0, II... >)
For a sequence [head,tail...) return the single head element.
Definition: integersequence.hh:53
STL namespace.
Utilities for reduction like operations on ranges.
Provides the TupleVector class that augments std::tuple by operator[].
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden & Uni Heidelberg  |  generated with Hugo v0.111.3 (Jan 9, 23:34, 2026)