dune-typetree  2.7.1
treecontainer.hh
Go to the documentation of this file.
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>
13 #include <dune/common/tuplevector.hh>
14 
16 
17 namespace 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>
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>
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:
102  container_()
103  {}
104 
105  TreeContainerVectorBackend(Container&& container) :
106  container_(std::move(container))
107  {}
108 
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>
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
Dune::TypeTree::Detail::TreeContainerVectorBackend::TreeContainerVectorBackend
TreeContainerVectorBackend(Container &&container)
Definition: treecontainer.hh:105
Dune::TypeTree::UniformTreeContainer
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
Dune::TypeTree::Detail::TreeContainerVectorBackend::TreeContainerVectorBackend
TreeContainerVectorBackend()
Definition: treecontainer.hh:101
Dune::TypeTree::makeTreeContainer
auto makeTreeContainer(const Tree &tree, LeafToValue &&leafToValue)
Create container havin the same structure as the given tree.
Definition: treecontainer.hh:184
Dune::TypeTree::Detail::TreeContainerVectorBackend
Definition: treecontainer.hh:82
Dune::TypeTree::Detail::ContainerFactory::operator()
auto operator()(const Node &node)
Definition: treecontainer.hh:51
Dune::TypeTree::treePath
constexpr HybridTreePath< T... > treePath(const T &... t)
Constructs a new HybridTreePath from the given indices.
Definition: treepath.hh:188
Dune::TypeTree::Detail::LeafToDefaultConstructibleValue::operator()
auto operator()(const Node &node) const
Definition: treecontainer.hh:156
Dune::TypeTree::Detail::makeTreeContainerVectorBackend
auto makeTreeContainerVectorBackend(Container &&container)
Definition: treecontainer.hh:140
Dune::TypeTree::HybridTreePath
A hybrid version of TreePath that supports both compile time and run time indices.
Definition: treepath.hh:23
Dune::TypeTree::Detail::TreeContainerVectorBackend::data
Container & data()
Definition: treecontainer.hh:130
Dune::TypeTree::Detail::LeafToDefaultConstructibleValue
Definition: treecontainer.hh:153
Dune::TypeTree::Detail::ContainerFactory::ContainerFactory
ContainerFactory(LeafToValue leafToValue)
Create ContainerFactory.
Definition: treecontainer.hh:45
Dune::TypeTree::Detail::ContainerFactory
Definition: treecontainer.hh:34
Dune::TypeTree::Detail::TreeContainerVectorBackend::data
const Container & data() const
Definition: treecontainer.hh:125
Dune::TypeTree::Detail::TreeContainerVectorBackend::TreeContainerVectorBackend
TreeContainerVectorBackend(TreeContainerVectorBackend &&other)
Definition: treecontainer.hh:109
Dune::TypeTree::TreeContainer
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
Dune
Definition: accumulate_static.hh:13
treepath.hh