RecursiveForEach.hpp 2.71 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#pragma once

#include <array>
#include <tuple>
#include <vector>
#include <type_traits>
#include <utility>

#include <dune/common/tuplevector.hh>
#include <amdis/common/TypeTraits.hpp>

namespace AMDiS
{
  namespace Recursive
  {
    /// Default implementation of the recursive \ref forEach function.
    /**
     * \tparam V  The type of the container/value decayed to the raw type
     **/
    template <class V>
    struct ForEach
    {
      template <class Value, class F>
      static void impl(Value&& v, F&& f)
      {
        f(v);
      }
    };

    /// \brief Recursive application of a functor `f` to a hierarchic container of containers.
    /**
     * This utility function applies the given functor `f` to the "leaf" entries in
     * a hierarchic container. Therefore, the container is traversed recursively,
     * using specializations of the `ForEach<Container>::apply` class method.
     * If no specialization is provided, the function is applied to the whole container
     * or leaf entry, respectively.
     **/
    template <class Container, class F>
    void forEach(Container&& container, F&& f)
    {
      ForEach<TYPEOF(container)>::impl(container,f);
    }


    // specializations for container types

    template <class... TT>
    struct ForEach<std::tuple<TT...>>
    {
      using indices = std::make_index_sequence<sizeof...(TT)>;

      template <std::size_t... I, class Tuple, class F>
      static void impl2(std::index_sequence<I...>, Tuple&& tuple, F&& f)
      {
        using std::get;
        (Recursive::forEach(get<I>(tuple), f),...);
      }

      template <class Tuple, class F>
      static void impl(Tuple&& tuple, F&& f)
      {
        impl2(indices{}, tuple, f);
      }
    };

    template <class T1, class T2>
    struct ForEach<std::pair<T1,T2>>
    {
      template <class Pair, class F>
      static void impl(Pair&& pair, F&& f)
      {
        Recursive::forEach(pair.first, f);
        Recursive::forEach(pair.second, f);
      }
    };

    template <class... TT>
    struct ForEach<Dune::TupleVector<TT...>>
    {
      template <class Tuple, class F>
      static void impl(Tuple&& tuple, F&& f)
      {
        ForEach<std::tuple<TT...>>::impl(tuple, f);
      }
    };

    template <class T, std::size_t n>
    struct ForEach<std::array<T,n>>
    {
      template <class Array, class F>
      static void impl(Array&& a, F&& f)
      {
        for (auto&& ai : a)
          Recursive::forEach(ai, f);
      }
    };

    template <class T>
    struct ForEach<std::vector<T>>
    {
      template <class Vector, class F>
      static void impl(Vector&& v, F&& f)
      {
        for (auto&& vi : v)
          Recursive::forEach(vi, f);
      }
    };

  } // end namespace Recursive
} // end namespace AMDiS