"Fossies" - the Fresh Open Source Software Archive 
Member "dune-typetree-2.8.0/dune/typetree/utility.hh" (31 Aug 2021, 10839 Bytes) of package /linux/misc/dune/dune-typetree-2.8.0.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "utility.hh" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
2.8.0_vs_2.9.0.
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
13 #include <dune/common/shared_ptr.hh>
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
19 namespace Dune {
20 namespace TypeTree {
21
22 /** \addtogroup TypeTree
23 * \{
24 */
25
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 {
37 return stackobject_to_shared_ptr(t);
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
59 /**
60 * @brief Applies left fold to a binary operator
61 * @details End of recursion of the fold operator
62 *
63 * @param binary_op Binary functor (discarded)
64 * @param arg Final result of the fold expansion
65 * @return constexpr decltype(auto) Final result of the fold expansion
66 */
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
74 /**
75 * @brief Applies left fold to a binary operator
76 * @details This function allows to pipe the result of one evaluation of a
77 * binary operator into the next evaluation.
78 *
79 * - C++17: `(init op ... op pack);`
80 * - here: `left_fold(op, init, pack...);`
81 *
82 * @code {.c++}
83 * auto p = std::plus<>{};
84 * auto result_a = p(p(p(0,1),2),3);
85 * auto result_b = left_fold(std::move(p), 0, 1, 2, 3);
86 * // result_a is same as result_b
87 * @endcode
88 *
89 * @param binary_op Binary functor
90 * @param init Initial (left-most) value of the fold
91 * @param arg_0 First argument of the right side of the fold
92 * @param args Additional arguments of the right side of the fold
93 * @return constexpr decltype(auto) Final result of the fold expansion
94 */
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
158 //! Struct for obtaining some basic structural information about a TypeTree.
159 /**
160 * This struct extracts basic information about the passed TypeTree and
161 * presents them in a static way suitable for use as compile-time constants.
162 *
163 * \tparam Tree The TypeTree to examine.
164 * \tparam Tag Internal parameter, leave at default value.
165 */
166 template<typename Tree, typename Tag = StartTag>
167 struct TreeInfo
168 {
169
170 private:
171 // Start the tree traversal
172 typedef TreeInfo<Tree,NodeTag<Tree>> NodeInfo;
173
174 public:
175
176 //! The depth of the TypeTree.
177 static const std::size_t depth = NodeInfo::depth;
178
179 //! The total number of nodes in the TypeTree.
180 static const std::size_t nodeCount = NodeInfo::nodeCount;
181
182 //! The number of leaf nodes in the TypeTree.
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
289 using Dune::index_constant;
290 namespace Indices = Dune::Indices;
291
292 //! No-op function to make calling a function on a variadic template argument pack legal C++.
293 template<typename... Args>
294 void discard(Args&&... args)
295 {}
296
297 //! Policies for the function apply_to_tuple().
298 namespace apply_to_tuple_policy {
299
300 //! Do not pass the index of the current tuple to the functor
301 struct no_pass_index {};
302
303 //! Pass the index of the current tuple to the functor as its first argument in a std::integral_constant.
304 struct pass_index {};
305
306 //! Default policy.
307 typedef no_pass_index default_policy;
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
329 //! Apply a functor to each element of a std::tuple.
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>
338 void apply_to_tuple(T&& t, F&& f, Policy = apply_to_tuple_policy::default_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
349 //! \} group TypeTree
350
351 } // namespace TypeTree
352 } //namespace Dune
353
354 #endif // DUNE_TYPETREE_UTILITY_HH