4#ifndef DUNE_TYPETREE_TREECONTAINER_HH
5#define DUNE_TYPETREE_TREECONTAINER_HH
12#include <dune/common/indices.hh>
13#include <dune/common/hybridutilities.hh>
14#include <dune/common/rangeutilities.hh>
15#include <dune/common/tuplevector.hh>
17#include <dune/typetree/treepath.hh>
35 template<
class LeafToValue>
36 class ContainerFactory
39 using DynamicDegreeConcept =
decltype((std::size_t(std::declval<N>().
degree()),
true));
42 using StaticDegreeConcept =
decltype((std::integral_constant<std::size_t,
N::degree()>{},
true));
45 using DynamicChildAccessConcept =
decltype((std::declval<N>().child(0u),
true));
56 ContainerFactory(LeafToValue leafToValue) :
57 leafToValue_(leafToValue)
61 auto operator()(
const Node& node)
63 return (*
this)(node, Dune::PriorityTag<5>{});
69 std::enable_if_t<Node::isLeaf, bool> =
true>
70 auto operator()(
const Node& node, Dune::PriorityTag<4>)
72 return leafToValue_(node);
76 StaticDegreeConcept<Node> =
true,
77 DynamicChildAccessConcept<Node> =
true>
78 auto operator()(
const Node& node, Dune::PriorityTag<3>)
80 return Dune::unpackIntegerSequence([&](
auto... indices) {
81 return std::array{(*this)(node.child(indices))...};
82 }, std::make_index_sequence<std::size_t(Node::degree())>());
86 DynamicDegreeConcept<Node> =
true,
87 DynamicChildAccessConcept<Node> =
true>
88 auto operator()(
const Node& node, Dune::PriorityTag<2>)
90 using TransformedChild =
decltype((*this)(node.child(0)));
91 std::vector<TransformedChild> container;
92 container.reserve(node.degree());
93 for (std::size_t i = 0; i < node.degree(); ++i)
94 container.emplace_back((*
this)(node.child(i)));
99 StaticDegreeConcept<Node> =
true>
100 auto operator()(
const Node& node, Dune::PriorityTag<1>)
102 return Dune::unpackIntegerSequence([&](
auto... indices) {
103 return Dune::makeTupleVector((*
this)(node.child(indices))...);
104 }, std::make_index_sequence<std::size_t(Node::degree())>());
108 LeafToValue leafToValue_;
115 template<
class Container>
116 class TreeContainerVectorBackend
119 static constexpr decltype(
auto) accessByTreePath(C&& container,
const HybridTreePath<>& path)
124 template<
class C,
class... T>
125 static constexpr decltype(
auto) accessByTreePath(C&& container,
const HybridTreePath<T...>& path)
127 auto head = path[Dune::Indices::_0];
128 auto tailPath = Dune::unpackIntegerSequence([&](
auto... i){
130 }, std::make_index_sequence<
sizeof...(T)-1>());
131 return accessByTreePath(container[head], tailPath);
134 template<
class C,
class Tree,
135 std::enable_if_t<Tree::isLeaf, bool> =
true>
136 static void resizeImpl(C& ,
const Tree& , Dune::PriorityTag<2>)
141 template<
class C,
class Tree,
142 class =
decltype(std::declval<C>().resize(0u))>
143 static void resizeImpl(C& container,
const Tree& tree, Dune::PriorityTag<1>)
145 container.resize(tree.degree());
146 Dune::Hybrid::forEach(Dune::range(tree.degree()), [&](
auto i) {
147 resizeImpl(container[i], tree.child(i), Dune::PriorityTag<5>{});
151 template<
class C,
class Tree>
152 static void resizeImpl(C& container,
const Tree& tree, Dune::PriorityTag<0>)
154 Dune::Hybrid::forEach(Dune::range(tree.degree()), [&](
auto i) {
155 resizeImpl(container[i], tree.child(i), Dune::PriorityTag<5>{});
160 using TypeTreeConcept =
decltype((
161 std::declval<T>().degree(),
169 TreeContainerVectorBackend(Container&& container) :
170 container_(std::move(container))
174 template <
class Tree, TypeTreeConcept<Tree> = true>
175 TreeContainerVectorBackend(
const Tree& tree) :
176 TreeContainerVectorBackend()
182 template <
class C = Container,
183 std::enable_if_t<std::is_default_constructible_v<C>,
bool> =
true>
184 TreeContainerVectorBackend() :
189 decltype(
auto)
operator[](
const HybridTreePath<T...>& path)
const
191 return accessByTreePath(container_, path);
195 decltype(
auto)
operator[](
const HybridTreePath<T...>& path)
197 return accessByTreePath(container_, path);
201 template<
class Tree, TypeTreeConcept<Tree> = true>
202 void resize(
const Tree& tree)
204 resizeImpl(container_, tree, Dune::PriorityTag<5>{});
207 const Container& data()
const
218 Container container_;
221 template<
class Container>
222 auto makeTreeContainerVectorBackend(Container&& container)
224 return TreeContainerVectorBackend<std::decay_t<Container>>(std::forward<Container>(container));
234 template<
template<
class Node>
class LeafToValue>
235 struct LeafToDefaultConstructibleValue
238 auto operator()(
const Node& node)
const
240 return LeafToValue<Node>{};
265 template<
class Tree,
class LeafToValue>
268 auto f = std::ref(leafToValue);
269 auto factory = Detail::ContainerFactory<decltype(f)>(f);
270 return Detail::makeTreeContainerVectorBackend(factory(tree));
288 template<
class Value,
class Tree>
297 template<
class Value,
class Tree>
303 template<
template<
class Node>
class LeafToValue,
class Tree>
304 using TreeContainer = std::decay_t<decltype(makeTreeContainer(std::declval<const Tree&>(), std::declval<Detail::LeafToDefaultConstructibleValue<LeafToValue>>()))>;
std::size_t degree(const Node &node)
Returns the degree of node as run time information.
Definition: nodeinterface.hh:76
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:298
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:304
auto makeTreeContainer(const Tree &tree)
Create container havin the same structure as the given tree.
Definition: treecontainer.hh:289