Dune Core Modules (2.8.0)

utility.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_UTILITY_HH
5#define DUNE_TYPETREE_UTILITY_HH
6
7#include <memory>
8#include <tuple>
9#include <type_traits>
10#include <utility>
11#include <algorithm>
12
14#include <dune/common/indices.hh>
15#include <dune/common/hybridutilities.hh>
16#include <dune/typetree/nodeinterface.hh>
17#include <dune/typetree/nodetags.hh>
18
19namespace Dune {
20 namespace TypeTree {
21
26#ifndef DOXYGEN
27
28 template<typename T>
29 std::shared_ptr<T> convert_arg(const T& t)
30 {
31 return std::make_shared<T>(t);
32 }
33
34 template<typename T>
35 std::shared_ptr<T> convert_arg(T& t)
36 {
38 }
39
40 template<typename BaseType, typename T>
41 T& assertGridViewType(T& t)
42 {
43 static_assert((std::is_same<typename BaseType::Traits::GridViewType,
44 typename T::Traits::GridViewType>::value),
45 "GridViewType must be equal in all components of composite type");
46 return t;
47 }
48
49 // only bind to real rvalues
50 template<typename T>
51 typename std::enable_if<!std::is_lvalue_reference<T>::value,std::shared_ptr<T> >::type convert_arg(T&& t)
52 {
53 return std::make_shared<T>(std::forward<T>(t));
54 }
55
56
57 namespace Experimental {
58
67 template<class BinaryOp, class Arg>
68 constexpr decltype(auto)
69 left_fold(BinaryOp&& binary_op, Arg&& arg)
70 {
71 return std::forward<Arg>(arg);
72 }
73
95 template<class BinaryOp, class Init, class Arg0, class... Args>
96 constexpr decltype(auto)
97 left_fold(BinaryOp&& binary_op, Init&& init, Arg0&& arg_0, Args&&... args)
98 {
99 return left_fold(
100 std::forward<BinaryOp>(binary_op),
101 binary_op(std::forward<Init>(init), std::forward<Arg0>(arg_0)),
102 std::forward<Args>(args)...);
103 }
104
105
106 namespace Hybrid {
107 using namespace Dune::Hybrid;
108
109 namespace Detail {
110 template<class Op, class... Args>
111 constexpr auto applyOperator(Op&& op, Args&&... args)
112 {
113 using T = std::common_type_t<Args...>;
114 return op(static_cast<T>(args)...);
115 }
116
117 template<class Op, class T, T... Args>
118 constexpr auto applyOperator(Op, std::integral_constant<T,Args>...)
119 {
120 static_assert(std::is_default_constructible_v<Op>,
121 "Operator in integral expressions shall be default constructible");
122 constexpr auto result = Op{}(T{Args}...);
123 return std::integral_constant<std::decay_t<decltype(result)>,result>{};
124 }
125
126 // FIXME: use lambda when we adpot c++20
127 struct Max {
128 template<class... Args>
129 constexpr auto operator()(Args&&... args) const
130 {
131 using T = std::common_type_t<Args...>;
132 return std::max({static_cast<T>(args)...});
133 }
134 };
135 }
136
137 static constexpr auto max = [](const auto& a, const auto& b)
138 {
139 return Detail::applyOperator(Detail::Max{}, a, b);
140 };
141
142 static constexpr auto plus = [](const auto& a, const auto& b)
143 {
144 return Detail::applyOperator(std::plus<>{}, a, b);
145 };
146
147 static constexpr auto minus = [](const auto& a, const auto& b)
148 {
149 return Detail::applyOperator(std::minus<>{}, a, b);
150 };
151 } // namespace Hybrid
152
153 } // namespace Experimental
154
155
156#endif // DOXYGEN
157
159
166 template<typename Tree, typename Tag = StartTag>
167 struct TreeInfo
168 {
169
170 private:
171 // Start the tree traversal
173
174 public:
175
177 static const std::size_t depth = NodeInfo::depth;
178
180 static const std::size_t nodeCount = NodeInfo::nodeCount;
181
183 static const std::size_t leafCount = NodeInfo::leafCount;
184
185 };
186
187
188#ifndef DOXYGEN
189
190 // ********************************************************************************
191 // TreeInfo specializations for the different node types
192 // ********************************************************************************
193
194
195 // leaf node
196 template<typename Node>
197 struct TreeInfo<Node,LeafNodeTag>
198 {
199
200 static const std::size_t depth = 1;
201
202 static const std::size_t nodeCount = 1;
203
204 static const std::size_t leafCount = 1;
205
206 };
207
208
209 // power node - exploit the fact that all children are identical
210 template<typename Node>
211 struct TreeInfo<Node,PowerNodeTag>
212 {
213
214 typedef TreeInfo<typename Node::ChildType,NodeTag<typename Node::ChildType>> ChildInfo;
215
216 static const std::size_t depth = 1 + ChildInfo::depth;
217
218 static const std::size_t nodeCount = 1 + StaticDegree<Node>::value * ChildInfo::nodeCount;
219
220 static const std::size_t leafCount = StaticDegree<Node>::value * ChildInfo::leafCount;
221
222 };
223
224
225 namespace {
226
227 // TMP for iterating over the children of a composite node
228 // identical for both composite node implementations
229 template<typename Node, std::size_t k, std::size_t n>
230 struct generic_compositenode_children_info
231 {
232
233 typedef generic_compositenode_children_info<Node,k+1,n> NextChild;
234
235 // extract child info
236 typedef typename Node::template Child<k>::Type Child;
237 typedef NodeTag<Child> ChildTag;
238 typedef TreeInfo<Child,ChildTag> ChildInfo;
239
240 // combine information of current child with info about following children
241 static const std::size_t maxDepth = ChildInfo::depth > NextChild::maxDepth ? ChildInfo::depth : NextChild::maxDepth;
242
243 static const std::size_t nodeCount = ChildInfo::nodeCount + NextChild::nodeCount;
244
245 static const std::size_t leafCount = ChildInfo::leafCount + NextChild::leafCount;
246
247 };
248
249 // End of recursion
250 template<typename Node, std::size_t n>
251 struct generic_compositenode_children_info<Node,n,n>
252 {
253 static const std::size_t maxDepth = 0;
254
255 static const std::size_t nodeCount = 0;
256
257 static const std::size_t leafCount = 0;
258 };
259
260 } // anonymous namespace
261
262
263 // Struct for building information about composite node
264 template<typename Node>
265 struct GenericCompositeNodeInfo
266 {
267
268 typedef generic_compositenode_children_info<Node,0,StaticDegree<Node>::value> Children;
269
270 static const std::size_t depth = 1 + Children::maxDepth;
271
272 static const std::size_t nodeCount = 1 + Children::nodeCount;
273
274 static const std::size_t leafCount = Children::leafCount;
275
276 };
277
278
279 // CompositeNode: delegate to GenericCompositeNodeInfo
280 template<typename Node>
281 struct TreeInfo<Node,CompositeNodeTag>
282 : public GenericCompositeNodeInfo<Node>
283 {};
284
285
286#endif // DOXYGEN
287
288
290 namespace Indices = Dune::Indices;
291
293 template<typename... Args>
294 void discard(Args&&... args)
295 {}
296
298 namespace apply_to_tuple_policy {
299
301 struct no_pass_index {};
302
304 struct pass_index {};
305
308
309 }
310
311 namespace {
312
313 // version that does not pass index
314 template<typename T, typename F, std::size_t... i>
315 void _apply_to_tuple(T&& t, F&& f, std::index_sequence<i...>,apply_to_tuple_policy::no_pass_index)
316 {
317 discard((f(std::get<i>(std::forward<T>(t))),0)...);
318 }
319
320 // version that passes index
321 template<typename T, typename F, std::size_t... i>
322 void _apply_to_tuple(T&& t, F&& f, std::index_sequence<i...>,apply_to_tuple_policy::pass_index)
323 {
324 discard((f(index_constant<i>{},std::get<i>(std::forward<T>(t))),0)...);
325 }
326
327 }
328
330 /*
331 * This function applies the functor f to each element of the std::tuple t.
332 * It works for arbitrary combinations of const- and non const lvalues and rvalues.
333 * The function accepts an optional policy argument that can currently be used to make
334 * it pass the index of the current tuple argument to the functor as a compile time constant
335 * in addition to the tuple element itself.
336 */
337 template<typename T, typename F, typename Policy>
339 {
340 const std::size_t size = std::tuple_size<typename std::decay<T>::type>::value;
341 _apply_to_tuple(
342 std::forward<T>(t),
343 std::forward<F>(f),
344 std::make_index_sequence<size>{},
345 Policy()
346 );
347 }
348
350
351 } // namespace TypeTree
352} //namespace Dune
353
354#endif // DUNE_TYPETREE_UTILITY_HH
std::integral_constant< std::size_t, i > index_constant
An index constant with value i.
Definition: indices.hh:28
auto max(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::max()
Definition: defaults.hh:79
typename impl::_Child< Node, indices... >::type Child
Template alias for the type of a child node given by a list of child indices.
Definition: childextraction.hh:223
void apply_to_tuple(T &&t, F &&f, Policy=apply_to_tuple_policy::default_policy())
Apply a functor to each element of a std::tuple.
Definition: utility.hh:338
void discard(Args &&... args)
No-op function to make calling a function on a variadic template argument pack legal C++.
Definition: utility.hh:294
Namespace with predefined compile time indices for the range [0,19].
Definition: indices.hh:49
no_pass_index default_policy
Default policy.
Definition: utility.hh:307
Dune namespace.
Definition: alignedallocator.hh:11
std::shared_ptr< T > stackobject_to_shared_ptr(T &t)
Create a shared_ptr for a stack-allocated object.
Definition: shared_ptr.hh:70
This file implements several utilities related to std::shared_ptr.
Tag designating a leaf node.
Definition: nodetags.hh:16
Struct for obtaining some basic structural information about a TypeTree.
Definition: utility.hh:168
static const std::size_t leafCount
The number of leaf nodes in the TypeTree.
Definition: utility.hh:183
static const std::size_t depth
The depth of the TypeTree.
Definition: utility.hh:177
static const std::size_t nodeCount
The total number of nodes in the TypeTree.
Definition: utility.hh:180
Do not pass the index of the current tuple to the functor.
Definition: utility.hh:301
Pass the index of the current tuple to the functor as its first argument in a std::integral_constant.
Definition: utility.hh:304
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 22, 23:30, 2024)