TemplateMetaProgramming.h
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package ArmarXCore
19  * @author Raphael Grimm ( raphael dot grimm at kit dot edu)
20  * @date 2016
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 #pragma once
25 
26 #include <cstddef>
27 #include <tuple>
28 #include <type_traits>
29 
30 namespace armarx::meta
31 {
32  template <class T, class... Ts>
33  struct is_in_types : std::true_type
34  {
35  };
36 
37  template <class T, class T0, class... Ts>
38  struct is_in_types<T, T0, Ts...> :
39  std::bool_constant<std::is_same_v<T, T0> && is_in_types<T, Ts...>::value>
40  {
41  };
42  template <class T, class... Ts>
43  static constexpr bool is_in_types_v = is_in_types<T, Ts...>::value;
44 
45  /// @brief Removes rvalue ref from a type
46  template <class T>
48  {
49  using type = T;
50  };
51 
52  template <class T>
54  {
55  using type = T;
56  };
57  template <class T>
59 
60  /// @brief Helper for sfinae (is added in c++17)
61  template <class...>
62  using void_t = void;
63 
64  /**
65  * @brief Traits about templates taking only types as parameters.
66  *
67  * \ingroup core-utility
68  */
70  {
71  /**
72  * @brief Whether a type T is the instance of a given template Template. (this is the case for false)
73  */
74  template <template <class...> class Template, class T>
75  struct IsInstanceOf : std::false_type
76  {
77  };
78 
79  /**
80  * @brief Whether a type T is the instance of a given template Template. (this is the case for true)
81  */
82  template <template <class...> class Template, class... Params>
83  struct IsInstanceOf<Template, Template<Params...>> : std::true_type
84  {
85  };
86 
87  template <template <class...> class Template, class T>
88  static constexpr bool IsInstanceOfV = IsInstanceOf<Template, T>::value;
89 
90  template <class T, template <class...> class... Templates>
91  static constexpr bool IsInstanceOfAnyV = (IsInstanceOf<Templates, T>::value || ...);
92 
93  static_assert(!IsInstanceOfAnyV<int, RemoveRvalueReference, std::tuple>);
94  static_assert(
95  IsInstanceOfAnyV<RemoveRvalueReference<int>, RemoveRvalueReference, std::tuple>);
96  static_assert(IsInstanceOfAnyV<std::tuple<int>, RemoveRvalueReference, std::tuple>);
97 
98  template <class T>
99  struct DisassembleTemplate : std::false_type
100  {
101  };
102 
103  template <template <class...> class Template, class... Params>
104  struct DisassembleTemplate<Template<Params...>> : std::true_type
105  {
106  template <template <class...> class NewTemplate>
107  using ReplaceTemplate = NewTemplate<Params...>;
108 
109  template <class... NewParams>
110  using ReplaceParameters = Template<NewParams...>;
111  };
112  };
113 
114  /**
115  * @brief Get the type of the last element of a template parameter pack.
116  */
117  template <class T0, class... Ts>
118  using last_type = typename std::decay<
119  typename std::tuple_element<sizeof...(Ts), std::tuple<T0, Ts...>>::type>::type;
120 
121  /**
122  * @brief Get the type of the first element of a template parameter pack.
123  */
124  template <class T0, class... Ts>
125  using first_type = T0;
126  /**
127  * @brief Get the type of the second element of a template parameter pack.
128  */
129  template <class T0, class T1, class... Ts>
130  using second_type = T1;
131  /**
132  * @brief Get the type of the third element of a template parameter pack.
133  */
134  template <class T0, class T1, class T2, class... Ts>
135  using third_type = T2;
136 
137  template <std::size_t n, class... Ts>
138  struct NthType
139  {
140  };
141 
142  template <std::size_t n, class T0, class... Ts>
143  struct NthType<n, T0, Ts...>
144  {
145  using type =
146  typename std::decay<typename std::tuple_element<n, std::tuple<T0, Ts...>>::type>::type;
147  };
148 
149  /**
150  * @brief Get the type of the nth element of a template parameter pack.
151  */
152  template <std::size_t n, class T0, class... Ts>
153  using nth_type =
154  typename std::decay<typename std::tuple_element<n, std::tuple<T0, Ts...>>::type>::type;
155 
156  /**
157  * @brief Can be used to determine if there is an overload for std::to_string for a type T
158  *
159  * This is the default if there is no overload
160  */
161  template <class T, class = void>
162  struct HasToString : std::false_type
163  {
164  };
165 
166  /**
167  * @brief Can be used to determine if there is an overload for std::to_string for a type T
168  *
169  * This is the specialization if there is an overload.
170  */
171  template <class T>
172  struct HasToString<
173  T,
174  typename std::enable_if<
175  std::is_same<decltype(std::to_string(std::declval<T>()), int{}), int>::value>::type> :
176  std::true_type
177  {
178  };
179 
180  //can't use this since gcc is broken / sfinae is bad in c++11
181  //struct HasToString < T, void_t<decltype(std::to_string(std::declval<T>()))> > :std::true_type {};
182 
183 
184  /**
185  * @brief Can be used to determine if T has an at method accepting a type of IdxT
186  *
187  * This is the default if there is no method
188  */
189  template <class T, class IdxT, class = void>
190  struct HasAtMethod : std::false_type
191  {
192  };
193 
194  /**
195  * @brief Can be used to determine if T has an at method accepting a type of IdxT
196  *
197  * This is the specialization if there is a method
198  */
199  template <class T, class IdxT>
200  struct HasAtMethod<T,
201  IdxT,
202  typename std::enable_if<
203  std::is_same<decltype(std::declval<T>().at(std::declval<IdxT>()), int{}),
204  int>::value>::type> : std::true_type
205  {
206  };
207 
208  //can't use this since gcc is broken / sfinae is bad in c++11
209  //struct HasAtMethod< T, IdxT,void_t<decltype(std::declval<T>().at(std::declval<IdxT>()))>> : std::true_type {};
210 
211 #define ARMARX_META_MAKE_HAS_MEMBER_FNC_CHECK(CHECKNAME, FNCNAME, FNCSIG) \
212  template <class T> \
213  class CHECKNAME \
214  { \
215  struct one \
216  { \
217  }; \
218  struct two \
219  { \
220  one a, b; \
221  }; \
222  template <class C, C> \
223  struct classAndFncPtr; \
224  template <class C> \
225  static one has(classAndFncPtr<FNCSIG, &C::FNCNAME>*); \
226  template <class T2> \
227  static two has(...); \
228  \
229  public: \
230  static constexpr bool value = sizeof(has<T>(0)) == sizeof(one); \
231  }; \
232  template <class T> \
233  static constexpr bool CHECKNAME##_v = CHECKNAME<T>::value
234 
235  template <std::size_t...>
237  {
239  };
240 } // namespace armarx::meta
241 
242 namespace armarx::meta::detail
243 {
244  template <class S1, class S2>
246 
247  template <std::size_t... I1, std::size_t... I2>
249  IndexSequence<I1..., (sizeof...(I1) + I2)...>
250  {
251  };
252 
253  template <std::size_t N>
255 
256  template <>
258  {
259  };
260 
261  template <>
263  {
264  };
265 
266  template <std::size_t N>
267  struct MakeIndexSequence :
268  detail::ConcatIndexSequences<typename MakeIndexSequence<N / 2>::type,
269  typename MakeIndexSequence<N - N / 2>::type>
270  {
271  };
272 
273  template <std::size_t Lo, class>
275 
276  template <std::size_t Lo, std::size_t... Is>
278  {
279  using type = IndexSequence<Lo + Is...>;
280  };
281 
282  template <std::size_t Lo, std::size_t Hi>
283  struct MakeIndexRange : AddToIndexSequence<Lo, typename MakeIndexSequence<Hi - Lo>::type>
284  {
285  };
286 } // namespace armarx::meta::detail
287 
288 namespace armarx::meta
289 {
290  template <std::size_t N>
292 
293  template <std::size_t Lo, std::size_t Hi>
295 
296  template <class... Ts>
297  using MakeIndexSequenceFor = MakeIndexSequence<sizeof...(Ts)>;
298 } // namespace armarx::meta
299 
300 namespace armarx::meta::detail
301 {
302  /**
303  * @see armarx::meta::DecayAll
304  */
305  template <class T>
306  struct DecayAll
307  {
308  using type = typename std::decay<T>::type;
309  };
310 
311  /**
312  * @see armarx::meta::DecayAll
313  */
314  template <class T>
315  struct DecayAll<T*>
316  {
317  using type = typename DecayAll<T>::type;
318  };
319 
320  /**
321  * @see armarx::meta::DecayAll
322  */
323  template <class T, std::size_t N>
324  struct DecayAll<T[N]>
325  {
326  using type = typename DecayAll<T>::type;
327  };
328 } // namespace armarx::meta::detail
329 
330 namespace armarx::meta
331 {
332  /**
333  * @brief Similar to std::decay but also decays ptr and array
334  */
335  template <class T>
337 
338  template <class T>
339  struct Wrapper
340  {
341  using type = T;
342  };
343 
344  template <class Base, class... Ds>
345  struct IsBaseOf : std::true_type
346  {
347  };
348 
349  template <class Base, class D0, class... Ds>
350  struct IsBaseOf<Base, D0, Ds...> :
351  std::integral_constant<bool,
352  std::is_base_of<Base, D0>::value && IsBaseOf<Base, Ds...>::value>
353  {
354  };
355 } // namespace armarx::meta
356 
357 namespace armarx::meta
358 {
359  template <class T, class... Others>
360  static constexpr bool is_any_of_v = (std::is_same_v<T, Others> || ...);
361 }
362 
363 namespace armarx::meta
364 {
365  // from https://stackoverflow.com/questions/22758291/how-can-i-detect-if-a-type-can-be-streamed-to-an-stdostream
366  template <typename S, typename T>
368  {
369  template <typename SS, typename TT>
370  static auto test(int)
371  -> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
372 
373  template <typename, typename>
374  static auto test(...) -> std::false_type;
375 
376  public:
377  static const bool value = decltype(test<S, T>(0))::value;
378  };
379 } // namespace armarx::meta
armarx::meta::detail::DecayAll< T[N]>::type
typename DecayAll< T >::type type
Definition: TemplateMetaProgramming.h:326
armarx::meta::Wrapper
Definition: TemplateMetaProgramming.h:339
armarx::meta::detail
Definition: create_macro.h:14
armarx::meta::IsBaseOf
Definition: TemplateMetaProgramming.h:345
armarx::meta::NthType< n, T0, Ts... >::type
typename std::decay< typename std::tuple_element< n, std::tuple< T0, Ts... > >::type >::type type
Definition: TemplateMetaProgramming.h:146
armarx::meta::Wrapper::type
T type
Definition: TemplateMetaProgramming.h:341
armarx::meta::nth_type
typename std::decay< typename std::tuple_element< n, std::tuple< T0, Ts... > >::type >::type nth_type
Get the type of the nth element of a template parameter pack.
Definition: TemplateMetaProgramming.h:154
armarx::meta::RemoveRvalueReference< T && >::type
T type
Definition: TemplateMetaProgramming.h:55
armarx::meta::HasToString
Can be used to determine if there is an overload for std::to_string for a type T.
Definition: TemplateMetaProgramming.h:162
armarx::meta::third_type
T2 third_type
Get the type of the third element of a template parameter pack.
Definition: TemplateMetaProgramming.h:135
armarx::meta::TypeTemplateTraits
Traits about templates taking only types as parameters.
Definition: TemplateMetaProgramming.h:69
armarx::meta
Definition: PluginCfgStruct.h:31
armarx::meta::RemoveRvalueReferenceT
typename RemoveRvalueReference< T >::type RemoveRvalueReferenceT
Definition: TemplateMetaProgramming.h:58
armarx::meta::NthType
Definition: TemplateMetaProgramming.h:138
armarx::meta::is_streamable::value
static const bool value
Definition: TemplateMetaProgramming.h:377
armarx::meta::detail::DecayAll< T * >::type
typename DecayAll< T >::type type
Definition: TemplateMetaProgramming.h:317
armarx::meta::RemoveRvalueReference::type
T type
Definition: TemplateMetaProgramming.h:49
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:855
armarx::meta::detail::ConcatIndexSequences
Definition: TemplateMetaProgramming.h:245
armarx::meta::detail::DecayAll::type
typename std::decay< T >::type type
Definition: TemplateMetaProgramming.h:308
armarx::meta::RemoveRvalueReference
Removes rvalue ref from a type.
Definition: TemplateMetaProgramming.h:47
armarx::meta::second_type
T1 second_type
Get the type of the second element of a template parameter pack.
Definition: TemplateMetaProgramming.h:130
armarx::meta::is_streamable
Definition: TemplateMetaProgramming.h:367
armarx::meta::MakeIndexRange
typename detail::MakeIndexRange< Lo, Hi >::type MakeIndexRange
Definition: TemplateMetaProgramming.h:294
armarx::meta::MakeIndexSequenceFor
MakeIndexSequence< sizeof...(Ts)> MakeIndexSequenceFor
Definition: TemplateMetaProgramming.h:297
armarx::meta::TypeTemplateTraits::DisassembleTemplate< Template< Params... > >::ReplaceParameters
Template< NewParams... > ReplaceParameters
Definition: TemplateMetaProgramming.h:110
armarx::meta::detail::DecayAll
Definition: TemplateMetaProgramming.h:306
armarx::meta::first_type
T0 first_type
Get the type of the first element of a template parameter pack.
Definition: TemplateMetaProgramming.h:125
armarx::meta::TypeTemplateTraits::DisassembleTemplate
Definition: TemplateMetaProgramming.h:99
armarx::meta::detail::MakeIndexSequence
Definition: TemplateMetaProgramming.h:254
armarx::meta::HasAtMethod
Can be used to determine if T has an at method accepting a type of IdxT.
Definition: TemplateMetaProgramming.h:190
armarx::meta::void_t
void void_t
Helper for sfinae (is added in c++17)
Definition: TemplateMetaProgramming.h:62
std
Definition: Application.h:66
armarx::meta::last_type
typename std::decay< typename std::tuple_element< sizeof...(Ts), std::tuple< T0, Ts... > >::type >::type last_type
Get the type of the last element of a template parameter pack.
Definition: TemplateMetaProgramming.h:119
armarx::meta::detail::MakeIndexRange
Definition: TemplateMetaProgramming.h:283
armarx::meta::is_in_types
Definition: TemplateMetaProgramming.h:33
T
float T
Definition: UnscentedKalmanFilterTest.cpp:38
armarx::meta::MakeIndexSequence
typename detail::MakeIndexSequence< N >::type MakeIndexSequence
Definition: TemplateMetaProgramming.h:291
armarx::meta::TypeTemplateTraits::IsInstanceOf
Whether a type T is the instance of a given template Template.
Definition: TemplateMetaProgramming.h:75
armarx::meta::detail::AddToIndexSequence
Definition: TemplateMetaProgramming.h:274
armarx::meta::TypeTemplateTraits::DisassembleTemplate< Template< Params... > >::ReplaceTemplate
NewTemplate< Params... > ReplaceTemplate
Definition: TemplateMetaProgramming.h:107
armarx::meta::IndexSequence
Definition: TemplateMetaProgramming.h:236