Lodestar
An integrated real-time control package in C++
TemplateTools.hpp
1 //
2 // Created by Hamza El-Kebir on 12/22/21.
3 //
4 
5 #ifndef LODESTAR_TEMPLATETOOLS_HPP
6 #define LODESTAR_TEMPLATETOOLS_HPP
7 
8 #include "TemplateTraits.hpp"
9 #include "Indices.hpp"
10 #include <array>
11 
12 namespace ls {
13  namespace aux {
14  class TemplateTools {
15  public:
16  template <class, class>
17  struct concatenate;
18  template <class... TFirst, class... TSecond>
19  struct concatenate<::std::tuple<TFirst...>, ::std::tuple<TSecond...>> {
20  using type = ::std::tuple<TFirst..., TSecond...>;
21  };
22 
23  template <typename TType, template <typename ...> class TWrapper, bool isWrapped = TemplateTraits::isInstance<TType, TWrapper>::value>
24  struct wrap;
25 
26  template <typename TType, template <typename ...> class TWrapper>
27  struct wrap<TType, TWrapper, true> {
28  using type = TType;
29  };
30 
31  template <typename TType, template <typename ...> class TWrapper>
32  struct wrap<TType, TWrapper, false> {
33  using type = TWrapper<TType>;
34  };
35 
36  // https://stackoverflow.com/a/16853775
37  template<typename, typename>
39 
40  template<typename T, typename... Ts, template<typename...> class TT>
41  struct appendToTypeSequence<T, TT<Ts...>>
42  {
43  using type = TT<Ts..., T>;
44  };
45 
46  template<typename T, unsigned int N, template<typename...> class TT>
47  struct repeat
48  {
49  using type = typename
51  T,
52  typename repeat<T, N-1, TT>::type
53  >::type;
54  };
55 
56  template<typename T, template<typename...> class TT>
57  struct repeat<T, 0, TT>
58  {
59  using type = TT<>;
60  };
61 
62  // https://stackoverflow.com/a/57757301
63  template <typename T, int ... Is>
64  constexpr static std::array<T, sizeof...(Is)>
65  create_array_impl(T value, IndexSequence<Is...>)
66  {
67  // cast Is to void to remove the warning: unused value
68  return {{(static_cast<void>(Is), value)...}};
69  }
70 
71  template <int N, typename T>
72  constexpr static std::array<T, N>
73  create_array(const T& value)
74  {
75  return create_array_impl(value, (typename Indices<N>::type){});
76  }
77 
78  class Executors {
79  public:
80  // https://stackoverflow.com/a/6894436
81  template<std::size_t I = 0, typename FuncT, typename... Tp>
82  static typename std::enable_if<I == sizeof...(Tp), void>::type
83  forEach(std::tuple<Tp...> &, FuncT) // Unused arguments are given no names.
84  { }
85 
86  template<std::size_t I = 0, typename FuncT, typename... Tp>
87  static typename std::enable_if<I < sizeof...(Tp), void>::type
88  forEach(std::tuple<Tp...>& t, FuncT f)
89  {
90  f(std::get<I>(t));
91  forEach<I + 1, FuncT, Tp...>(t, f);
92  }
93 
94  template<std::size_t I = 0, typename FuncT, typename... Tp>
95  static typename std::enable_if<I == sizeof...(Tp), void>::type
96  forEachPointer(std::tuple<Tp...> &, FuncT) // Unused arguments are given no names.
97  { }
98 
99  template<std::size_t I = 0, typename FuncT, typename... Tp>
100  static typename std::enable_if<I < sizeof...(Tp), void>::type
101  forEachPointer(std::tuple<Tp...>& t, FuncT f)
102  {
103  f(&std::get<I>(t));
104  forEachPointer<I + 1, FuncT, Tp...>(t, f);
105  }
106 
107  protected:
108  // https://stackoverflow.com/a/6454211
109  template<int...> struct index_tuple{};
110 
111  template<int I, typename IndexTuple, typename... Types>
112  struct make_indices_impl;
113 
114  template<int I, int... Indexes, typename T, typename ... Types>
115  struct make_indices_impl<I, index_tuple<Indexes...>, T, Types...>
116  {
117  typedef typename make_indices_impl<I + 1, index_tuple<Indexes..., I>, Types...>::type type;
118  };
119 
120  template<int I, int... Indexes>
121  struct make_indices_impl<I, index_tuple<Indexes...> >
122  {
123  typedef index_tuple<Indexes...> type;
124  };
125 
126  template<typename ... Types>
127  struct make_indices : make_indices_impl<0, index_tuple<>, Types...>
128  {};
129 
130  public:
131  // Apply variadic function to tuple, wrapped in Wrapper
132  // Template template parameter magicks abound!
133  template<class Ret, class... Args, template <typename...> class Wrapper, int... Indexes >
134  static Ret applyWrapped_helper(std::function<Ret(Args...)> &pf, index_tuple< Indexes... >, std::tuple<Wrapper<Args>...>&& tup)
135  {
136  return pf( std::forward<Args>( std::get<Indexes>(tup).object)... );
137  }
138 
139  template<class Ret, class ... Args, template <typename...> class Wrapper>
140  static Ret applyWrapped(std::function<Ret(Args...)> &pf, const std::tuple<Wrapper<Args>...>& tup)
141  {
142  return applyWrapped_helper(pf, typename make_indices<Args...>::type(), std::tuple<Wrapper<Args>...>(tup));
143  }
144 
145  template<class Ret, class ... Args, template <typename...> class Wrapper>
146  static Ret applyWrapped(std::function<Ret(Args...)> &pf, std::tuple<Wrapper<Args>...>&& tup)
147  {
148  return applyWrapped_helper(pf, typename make_indices<Args...>::type(), std::forward<std::tuple<Wrapper<Args>...>>(tup));
149  }
150  };
151  };
152  }
153 }
154 
155 #endif //LODESTAR_TEMPLATETOOLS_HPP
Indices
Definition: Indices.hpp:15
ls::aux::TemplateTools::concatenate
Definition: TemplateTools.hpp:17
ls
Main Lodestar code.
Definition: BilinearTransformation.hpp:12
ls::aux::TemplateTools::repeat
Definition: TemplateTools.hpp:47
ls::aux::TemplateTools::wrap
Definition: TemplateTools.hpp:24
ls::aux::TemplateTools::appendToTypeSequence
Definition: TemplateTools.hpp:38
ls::aux::TemplateTraits::isInstance
Definition: TemplateTraits.hpp:22
ls::aux::TemplateTools::Executors
Definition: TemplateTools.hpp:78
ls::aux::TemplateTools
Definition: TemplateTools.hpp:14
IndexSequence
Definition: Indices.hpp:11