Dune Core Modules (2.7.0)

hybridutilities.hh
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3#ifndef DUNE_COMMON_HYBRIDUTILITIES_HH
4#define DUNE_COMMON_HYBRIDUTILITIES_HH
5
6#include <tuple>
7#include <utility>
8
12#include <dune/common/indices.hh>
13#include <dune/common/assertandreturn.hh>
14#include <dune/common/unused.hh>
16
17
18
19namespace Dune {
20namespace Hybrid {
21
22namespace Impl {
23
24 // Try if tuple_size is implemented for class
25 template<class T, int i>
26 constexpr auto size(const Dune::FieldVector<T, i>&, const PriorityTag<5>&)
27 -> decltype(std::integral_constant<std::size_t,i>())
28 {
29 return {};
30 }
31
32 // Try if tuple_size is implemented for class
33 template<class T>
34 constexpr auto size(const T&, const PriorityTag<3>&)
35 -> decltype(std::integral_constant<std::size_t,std::tuple_size<T>::value>())
36 {
37 return {};
38 }
39
40 // Try if there's a static constexpr size()
41 template<class T>
42 constexpr auto size(const T&, const PriorityTag<1>&)
43 -> decltype(std::integral_constant<std::size_t,T::size()>())
44 {
45 return {};
46 }
47
48 // As a last resort try if there's a static constexpr size()
49 template<class T>
50 constexpr auto size(const T& t, const PriorityTag<0>&)
51 {
52 return t.size();
53 }
54
55} // namespace Impl
56
57
58
80template<class T>
81constexpr auto size(const T& t)
82{
83 return Impl::size(t, PriorityTag<42>());
84}
85
86
87
88namespace Impl {
89
90 template<class Container, class Index,
91 std::enable_if_t<IsTuple<std::decay_t<Container>>::value, int> = 0>
92 constexpr decltype(auto) elementAt(Container&& c, Index&&, PriorityTag<2>)
93 {
94 return std::get<std::decay_t<Index>::value>(c);
95 }
96
97 template<class T, T... t, class Index>
98 constexpr decltype(auto) elementAt(std::integer_sequence<T, t...> c, Index, PriorityTag<1>)
99 {
100 return Dune::integerSequenceEntry(c, std::integral_constant<std::size_t, Index::value>());
101 }
102
103 template<class Container, class Index>
104 constexpr decltype(auto) elementAt(Container&& c, Index&& i, PriorityTag<0>)
105 {
106 return c[i];
107 }
108
109} // namespace Impl
110
111
112
133template<class Container, class Index>
134constexpr decltype(auto) elementAt(Container&& c, Index&& i)
135{
136 return Impl::elementAt(std::forward<Container>(c), std::forward<Index>(i), PriorityTag<42>());
137}
138
139
140
141namespace Impl {
142
143 template<class Begin, class End,
144 std::enable_if_t<IsIntegralConstant<Begin>::value and IsIntegralConstant<End>::value, int> = 0>
145 constexpr auto integralRange(const Begin& /*begin*/, const End& /*end*/, const PriorityTag<1>&)
146 {
147 static_assert(Begin::value <= End::value, "You cannot create an integralRange where end<begin");
149 }
150
151 // This should be constexpr but gcc-4.9 does not support
152 // the relaxed constexpr requirements. Hence for being
153 // constexpr the function body can only contain a return
154 // statement and no assertion before this.
155 template<class Begin, class End>
156 constexpr auto integralRange(const Begin& begin, const End& end, const PriorityTag<0>&)
157 {
158 return DUNE_ASSERT_AND_RETURN(begin<=end, Dune::IntegralRange<End>(begin, end));
159 }
160
161} // namespace Impl
162
163
164
182template<class Begin, class End>
183constexpr auto integralRange(const Begin& begin, const End& end)
184{
185 return Impl::integralRange(begin, end, PriorityTag<42>());
186}
187
201template<class End>
202constexpr auto integralRange(const End& end)
203{
205}
206
207
208
209namespace Impl {
210
211 template<class T>
212 void evaluateFoldExpression(std::initializer_list<T>&&)
213 {}
214
215 template<class Range, class F, class Index, Index... i>
216 constexpr void forEachIndex(Range&& range, F&& f, std::integer_sequence<Index, i...>)
217 {
218 evaluateFoldExpression<int>({(f(Hybrid::elementAt(range, std::integral_constant<Index,i>())), 0)...});
219 }
220
221 template<class F, class Index, Index... i>
222 constexpr void forEach(std::integer_sequence<Index, i...> /*range*/, F&& f, PriorityTag<2>)
223 {
224 evaluateFoldExpression<int>({(f(std::integral_constant<Index,i>()), 0)...});
225 }
226
227
228 template<class Range, class F,
229 std::enable_if_t<IsIntegralConstant<decltype(Hybrid::size(std::declval<Range>()))>::value, int> = 0>
230 constexpr void forEach(Range&& range, F&& f, PriorityTag<1>)
231 {
232 auto size = Hybrid::size(range);
233 auto indices = std::make_index_sequence<size>();
234 (forEachIndex)(std::forward<Range>(range), std::forward<F>(f), indices);
235 }
236
237 template<class Range, class F>
238 constexpr void forEach(Range&& range, F&& f, PriorityTag<0>)
239 {
240 for(auto&& e : range)
241 f(e);
242 }
243
244} // namespace Impl
245
246
247
266template<class Range, class F>
267constexpr void forEach(Range&& range, F&& f)
268{
269 Impl::forEach(std::forward<Range>(range), std::forward<F>(f), PriorityTag<42>());
270}
271
272
273
289template<class Range, class T, class F>
290T accumulate(Range&& range, T value, F&& f)
291{
292 forEach(std::forward<Range>(range), [&](auto&& entry) {
293 value = f(value, entry);
294 });
295 return value;
296}
297
298
299
300namespace Impl {
301
302 struct Id {
303 template<class T>
304 constexpr T operator()(T&& x) const {
305 return std::forward<T>(x);
306 }
307 };
308
309 template<class IfFunc, class ElseFunc>
310 constexpr decltype(auto) ifElse(std::true_type, IfFunc&& ifFunc, ElseFunc&& /*elseFunc*/)
311 {
312 return ifFunc(Id{});
313 }
314
315 template<class IfFunc, class ElseFunc>
316 constexpr decltype(auto) ifElse(std::false_type, IfFunc&& /*ifFunc*/, ElseFunc&& elseFunc)
317 {
318 return elseFunc(Id{});
319 }
320
321 template<class IfFunc, class ElseFunc>
322 decltype(auto) ifElse(const bool& condition, IfFunc&& ifFunc, ElseFunc&& elseFunc)
323 {
324 if (condition)
325 return ifFunc(Id{});
326 else
327 return elseFunc(Id{});
328 }
329
330} // namespace Impl
331
332
333
354template<class Condition, class IfFunc, class ElseFunc>
355decltype(auto) ifElse(const Condition& condition, IfFunc&& ifFunc, ElseFunc&& elseFunc)
356{
357 return Impl::ifElse(condition, std::forward<IfFunc>(ifFunc), std::forward<ElseFunc>(elseFunc));
358}
359
367template<class Condition, class IfFunc>
368void ifElse(const Condition& condition, IfFunc&& ifFunc)
369{
370 ifElse(condition, std::forward<IfFunc>(ifFunc), [](auto&& i) { DUNE_UNUSED_PARAMETER(i); });
371}
372
373
374
375namespace Impl {
376
377 template<class T1, class T2>
378 constexpr auto equals(const T1& /*t1*/, const T2& /*t2*/, PriorityTag<1>) -> decltype(T1::value, T2::value, std::integral_constant<bool,T1::value == T2::value>())
379 { return {}; }
380
381 template<class T1, class T2>
382 constexpr auto equals(const T1& t1, const T2& t2, PriorityTag<0>)
383 {
384 return t1==t2;
385 }
386
387} // namespace Impl
388
389
390
400template<class T1, class T2>
401constexpr auto equals(T1&& t1, T2&& t2)
402{
403 return Impl::equals(std::forward<T1>(t1), std::forward<T2>(t2), PriorityTag<1>());
404}
405
406
407
408namespace Impl {
409
410 template<class Result, class T, class Value, class Branches, class ElseBranch>
411 constexpr Result switchCases(std::integer_sequence<T>, const Value& /*value*/, Branches&& /*branches*/, ElseBranch&& elseBranch)
412 {
413 return elseBranch();
414 }
415
416 template<class Result, class T, T t0, T... tt, class Value, class Branches, class ElseBranch>
417 constexpr Result switchCases(std::integer_sequence<T, t0, tt...>, const Value& value, Branches&& branches, ElseBranch&& elseBranch)
418 {
419 return ifElse(
420 Hybrid::equals(std::integral_constant<T, t0>(), value),
421 [&](auto id) -> decltype(auto) {
422 return id(branches)(std::integral_constant<T, t0>());
423 }, [&](auto id) -> decltype(auto) {
424 return Impl::switchCases<Result>(id(std::integer_sequence<T, tt...>()), value, branches, elseBranch);
425 });
426 }
427
428} // namespace Impl
429
430
431
459template<class Cases, class Value, class Branches, class ElseBranch>
460constexpr decltype(auto) switchCases(const Cases& cases, const Value& value, Branches&& branches, ElseBranch&& elseBranch)
461{
462 return Impl::switchCases<decltype(elseBranch())>(cases, value, std::forward<Branches>(branches), std::forward<ElseBranch>(elseBranch));
463}
464
485template<class Cases, class Value, class Branches>
486constexpr void switchCases(const Cases& cases, const Value& value, Branches&& branches)
487{
488 return Impl::switchCases<void>(cases, value, std::forward<Branches>(branches), []() {});
489}
490
491
492} // namespace Hybrid
493} // namespace Dune
494
495
496#endif // #ifndef DUNE_COMMON_HYBRIDUTILITIES_HH
vector space out of a tensor product of fields.
Definition: fvector.hh:96
dynamic integer range for use in range-based for loops
Definition: rangeutilities.hh:172
static integer range for use in range-based for loops
Definition: rangeutilities.hh:222
Implements a vector constructed from a given type representing a field and a compile-time given size.
constexpr index_constant< 0 > _0
Compile time index with value 0.
Definition: indices.hh:51
constexpr auto integerSequenceEntry(std::integer_sequence< T, t... >, std::integral_constant< std::size_t, index > i)
Get entry of std::integer_sequence.
Definition: typetraits.hh:543
#define DUNE_ASSERT_AND_RETURN(C, X)
Asserts a condition and return on success in constexpr context.
Definition: assertandreturn.hh:20
#define DUNE_UNUSED_PARAMETER(parm)
A macro to mark intentionally unused function parameters with.
Definition: unused.hh:25
void ifElse(const Condition &condition, IfFunc &&ifFunc)
A conditional expression.
Definition: hybridutilities.hh:368
constexpr auto size(const T &t)
Size query.
Definition: hybridutilities.hh:81
constexpr auto integralRange(const End &end)
Create an integral range starting from 0.
Definition: hybridutilities.hh:202
constexpr auto equals(T1 &&t1, T2 &&t2)
Equality comparison.
Definition: hybridutilities.hh:401
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:267
T accumulate(Range &&range, T value, F &&f)
Accumulate values.
Definition: hybridutilities.hh:290
constexpr void switchCases(const Cases &cases, const Value &value, Branches &&branches)
Switch statement.
Definition: hybridutilities.hh:486
constexpr decltype(auto) elementAt(Container &&c, Index &&i)
Get element at given position from container.
Definition: hybridutilities.hh:134
Dune namespace.
Definition: alignedallocator.hh:14
Utilities for reduction like operations on ranges.
Check if T is an std::integral_constant<I, i>
Definition: typetraits.hh:465
Helper class for tagging priorities.
Definition: typeutilities.hh:71
Traits for type conversions and type information.
Utilities for type computations, constraining overloads, ...
Definition of the DUNE_UNUSED macro for the case that config.h is not available.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)