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 <type_traits>
27 #include <tuple>
28 #include <cstddef>
29 
30 namespace armarx::meta
31 {
32  template<class T, class...Ts>
33  struct is_in_types : std::true_type
34  {};
35  template<class T, class T0, class...Ts>
36  struct is_in_types<T, T0, Ts...> :
37  std::bool_constant
38  <
39  std::is_same_v<T, T0>&&
40  is_in_types<T, Ts...>::value
41  >
42  {};
43  template<class T, class...Ts>
44  static constexpr bool is_in_types_v = is_in_types<T, Ts...>::value;
45 
46  /// @brief Removes rvalue ref from a type
47  template<class T> struct RemoveRvalueReference
48  {
49  using type = T;
50  };
51  template<class T> struct RemoveRvalueReference < T&& >
52  {
53  using type = T;
54  };
55  template<class T> using RemoveRvalueReferenceT = typename RemoveRvalueReference<T>::type;
56 
57  /// @brief Helper for sfinae (is added in c++17)
58  template<class...>
59  using void_t = void;
60 
61  /**
62  * @brief Traits about templates taking only types as parameters.
63  *
64  * \ingroup core-utility
65  */
67  {
68  /**
69  * @brief Whether a type T is the instance of a given template Template. (this is the case for false)
70  */
71  template<template<class...> class Template, class T > struct IsInstanceOf : std::false_type {};
72  /**
73  * @brief Whether a type T is the instance of a given template Template. (this is the case for true)
74  */
75  template<template<class...> class Template, class...Params> struct IsInstanceOf<Template, Template<Params...>> : std:: true_type {};
76 
77  template<template<class...> class Template, class T>
78  static constexpr bool IsInstanceOfV = IsInstanceOf<Template, T>::value;
79 
80  template<class T, template<class...> class...Templates>
81  static constexpr bool IsInstanceOfAnyV = (IsInstanceOf<Templates, T>::value || ...);
82 
83  static_assert(!IsInstanceOfAnyV<int, RemoveRvalueReference, std::tuple>);
84  static_assert(IsInstanceOfAnyV<RemoveRvalueReference<int>, RemoveRvalueReference, std::tuple>);
85  static_assert(IsInstanceOfAnyV<std::tuple<int>, RemoveRvalueReference, std::tuple>);
86 
87  template<class T>
88  struct DisassembleTemplate : std::false_type {};
89  template<template<class...> class Template, class...Params>
90  struct DisassembleTemplate<Template<Params...>> : std:: true_type
91  {
92  template<template<class...> class NewTemplate>
93  using ReplaceTemplate = NewTemplate<Params...>;
94 
95  template<class...NewParams>
96  using ReplaceParameters = Template<NewParams...>;
97  };
98  };
99 
100  /**
101  * @brief Get the type of the last element of a template parameter pack.
102  */
103  template<class T0, class...Ts>
104  using last_type = typename std::decay < typename std::tuple_element < sizeof...(Ts), std::tuple<T0, Ts... >>::type >::type;
105 
106  /**
107  * @brief Get the type of the first element of a template parameter pack.
108  */
109  template<class T0, class...Ts>
110  using first_type = T0;
111  /**
112  * @brief Get the type of the second element of a template parameter pack.
113  */
114  template<class T0, class T1, class...Ts>
115  using second_type = T1;
116  /**
117  * @brief Get the type of the third element of a template parameter pack.
118  */
119  template<class T0, class T1, class T2, class...Ts>
120  using third_type = T2;
121 
122 
123  template<std::size_t n, class...Ts>
124  struct NthType {};
125  template<std::size_t n, class T0, class...Ts>
126  struct NthType<n, T0, Ts...>
127  {
128  using type = typename std::decay < typename std::tuple_element < n, std::tuple<T0, Ts... >>::type >::type;
129  };
130 
131  /**
132  * @brief Get the type of the nth element of a template parameter pack.
133  */
134  template<std::size_t n, class T0, class...Ts>
135  using nth_type = typename std::decay < typename std::tuple_element < n, std::tuple<T0, Ts... >>::type >::type;
136 
137  /**
138  * @brief Can be used to determine if there is an overload for std::to_string for a type T
139  *
140  * This is the default if there is no overload
141  */
142  template<class T, class = void>
143  struct HasToString : std::false_type {};
144 
145  /**
146  * @brief Can be used to determine if there is an overload for std::to_string for a type T
147  *
148  * This is the specialization if there is an overload.
149  */
150  template<class T>
151 struct HasToString < T, typename std::enable_if < std::is_same < decltype(std::to_string(std::declval<T>()), int {}), int >::value >::type > :
152  std::true_type {};
153  //can't use this since gcc is broken / sfinae is bad in c++11
154  //struct HasToString < T, void_t<decltype(std::to_string(std::declval<T>()))> > :std::true_type {};
155 
156 
157  /**
158  * @brief Can be used to determine if T has an at method accepting a type of IdxT
159  *
160  * This is the default if there is no method
161  */
162  template<class T, class IdxT, class = void>
163  struct HasAtMethod : std::false_type {};
164 
165  /**
166  * @brief Can be used to determine if T has an at method accepting a type of IdxT
167  *
168  * This is the specialization if there is a method
169  */
170  template<class T, class IdxT>
171 struct HasAtMethod < T, IdxT, typename std::enable_if < std::is_same < decltype(std::declval<T>().at(std::declval<IdxT>()), int {}), int >::value >::type > :
172  std::true_type {};
173  //can't use this since gcc is broken / sfinae is bad in c++11
174  //struct HasAtMethod< T, IdxT,void_t<decltype(std::declval<T>().at(std::declval<IdxT>()))>> : std::true_type {};
175 
176 #define ARMARX_META_MAKE_HAS_MEMBER_FNC_CHECK(CHECKNAME, FNCNAME, FNCSIG) \
177  template <class T> \
178  class CHECKNAME \
179  { \
180  struct one {}; \
181  struct two { one a, b; }; \
182  template<class C, C> struct classAndFncPtr; \
183  template<class C> \
184  static one has(classAndFncPtr<FNCSIG, &C::FNCNAME>*); \
185  template<class T2> \
186  static two has(...); \
187  public: \
188  static constexpr bool value = sizeof(has<T>(0)) == sizeof(one); \
189  }; \
190  template <class T> \
191  static constexpr bool CHECKNAME##_v = CHECKNAME<T>::value
192 
193  template<std::size_t...>
195  {
197  };
198 }
199 namespace armarx::meta::detail
200 {
201  template<class S1, class S2>
203  template<std::size_t... I1, std::size_t... I2>
205  : IndexSequence < I1..., (sizeof...(I1) + I2)... > {};
206 
207  template<std::size_t N> struct MakeIndexSequence;
208  template<> struct MakeIndexSequence<0> : IndexSequence<> {};
209  template<> struct MakeIndexSequence<1> : IndexSequence<0> {};
210  template<std::size_t N> struct MakeIndexSequence
212  typename MakeIndexSequence < N / 2 >::type,
213  typename MakeIndexSequence < N - N / 2 >::type
214  > {};
215 
216  template<std::size_t Lo, class>
218 
219  template<std::size_t Lo, std::size_t...Is>
221  {
222  using type = IndexSequence < Lo + Is ... >;
223  };
224 
225  template<std::size_t Lo, std::size_t Hi>
226  struct MakeIndexRange : AddToIndexSequence < Lo, typename MakeIndexSequence < Hi - Lo >::type >
227  {};
228 }
229 
230 namespace armarx::meta
231 {
232  template<std::size_t N>
234 
235  template<std::size_t Lo, std::size_t Hi>
237 
238  template<class...Ts>
239  using MakeIndexSequenceFor = MakeIndexSequence<sizeof...(Ts)>;
240 }
241 namespace armarx::meta::detail
242 {
243  /**
244  * @see armarx::meta::DecayAll
245  */
246  template<class T>
247  struct DecayAll
248  {
249  using type = typename std::decay<T>::type;
250  };
251  /**
252  * @see armarx::meta::DecayAll
253  */
254  template<class T>
255  struct DecayAll<T*>
256  {
257  using type = typename DecayAll<T>::type;
258  };
259  /**
260  * @see armarx::meta::DecayAll
261  */
262  template<class T, std::size_t N>
263  struct DecayAll<T[N]>
264  {
265  using type = typename DecayAll<T>::type;
266  };
267 }
268 
269 namespace armarx::meta
270 {
271  /**
272  * @brief Similar to std::decay but also decays ptr and array
273  */
274  template<class T>
276 
277  template<class T>
278  struct Wrapper
279  {
280  using type = T;
281  };
282 
283  template<class Base, class...Ds>
284  struct IsBaseOf : std::true_type {};
285  template<class Base, class D0, class...Ds>
286  struct IsBaseOf<Base, D0, Ds...> :
287  std::integral_constant <
288  bool,
289  std::is_base_of<Base, D0> ::value&&
290  IsBaseOf<Base, Ds...>::value
291  > {};
292 }
293 
294 namespace armarx::meta
295 {
296  template<class T, class...Others>
297  static constexpr bool is_any_of_v = (std::is_same_v<T, Others> || ...);
298 }
299 
300 namespace armarx::meta
301 {
302  // from https://stackoverflow.com/questions/22758291/how-can-i-detect-if-a-type-can-be-streamed-to-an-stdostream
303  template <typename S, typename T>
305  {
306  template <typename SS, typename TT>
307  static auto test(int) -> decltype(std::declval<SS&>() << std::declval<TT>(), std::true_type());
308 
309  template <typename, typename>
310  static auto test(...) -> std::false_type;
311 
312  public:
313  static const bool value = decltype(test<S, T>(0))::value;
314  };
315 }
316 
armarx::meta::detail::DecayAll< T[N]>::type
typename DecayAll< T >::type type
Definition: TemplateMetaProgramming.h:265
armarx::meta::Wrapper
Definition: TemplateMetaProgramming.h:278
armarx::meta::detail
Definition: create_macro.h:13
armarx::meta::IsBaseOf
Definition: TemplateMetaProgramming.h:284
armarx::meta::Wrapper::type
T type
Definition: TemplateMetaProgramming.h:280
armarx::meta::RemoveRvalueReference< T && >::type
T type
Definition: TemplateMetaProgramming.h:53
armarx::meta::HasToString
Can be used to determine if there is an overload for std::to_string for a type T.
Definition: TemplateMetaProgramming.h:143
armarx::meta::third_type
T2 third_type
Get the type of the third element of a template parameter pack.
Definition: TemplateMetaProgramming.h:120
armarx::meta::TypeTemplateTraits
Traits about templates taking only types as parameters.
Definition: TemplateMetaProgramming.h:66
armarx::meta
Definition: PluginCfgStruct.h:31
armarx::meta::RemoveRvalueReferenceT
typename RemoveRvalueReference< T >::type RemoveRvalueReferenceT
Definition: TemplateMetaProgramming.h:55
armarx::meta::NthType
Definition: TemplateMetaProgramming.h:124
armarx::meta::is_streamable::value
static const bool value
Definition: TemplateMetaProgramming.h:313
armarx::meta::detail::DecayAll< T * >::type
typename DecayAll< T >::type type
Definition: TemplateMetaProgramming.h:257
armarx::meta::RemoveRvalueReference::type
T type
Definition: TemplateMetaProgramming.h:49
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:128
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:926
armarx::meta::detail::ConcatIndexSequences
Definition: TemplateMetaProgramming.h:202
armarx::meta::detail::DecayAll::type
typename std::decay< T >::type type
Definition: TemplateMetaProgramming.h:249
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:115
armarx::meta::is_streamable
Definition: TemplateMetaProgramming.h:304
armarx::meta::MakeIndexRange
typename detail::MakeIndexRange< Lo, Hi >::type MakeIndexRange
Definition: TemplateMetaProgramming.h:236
armarx::meta::MakeIndexSequenceFor
MakeIndexSequence< sizeof...(Ts)> MakeIndexSequenceFor
Definition: TemplateMetaProgramming.h:239
armarx::meta::TypeTemplateTraits::DisassembleTemplate< Template< Params... > >::ReplaceParameters
Template< NewParams... > ReplaceParameters
Definition: TemplateMetaProgramming.h:96
armarx::meta::detail::DecayAll
Definition: TemplateMetaProgramming.h:247
armarx::meta::first_type
T0 first_type
Get the type of the first element of a template parameter pack.
Definition: TemplateMetaProgramming.h:110
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:135
armarx::meta::TypeTemplateTraits::DisassembleTemplate
Definition: TemplateMetaProgramming.h:88
armarx::meta::detail::MakeIndexSequence
Definition: TemplateMetaProgramming.h:207
armarx::meta::HasAtMethod
Can be used to determine if T has an at method accepting a type of IdxT.
Definition: TemplateMetaProgramming.h:163
armarx::meta::void_t
void void_t
Helper for sfinae (is added in c++17)
Definition: TemplateMetaProgramming.h:59
std
Definition: Application.h:66
armarx::meta::detail::MakeIndexRange
Definition: TemplateMetaProgramming.h:226
armarx::meta::is_in_types
Definition: TemplateMetaProgramming.h:33
T
float T
Definition: UnscentedKalmanFilterTest.cpp:35
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:104
armarx::meta::MakeIndexSequence
typename detail::MakeIndexSequence< N >::type MakeIndexSequence
Definition: TemplateMetaProgramming.h:233
armarx::meta::TypeTemplateTraits::IsInstanceOf
Whether a type T is the instance of a given template Template.
Definition: TemplateMetaProgramming.h:71
armarx::meta::detail::AddToIndexSequence
Definition: TemplateMetaProgramming.h:217
armarx::meta::TypeTemplateTraits::DisassembleTemplate< Template< Params... > >::ReplaceTemplate
NewTemplate< Params... > ReplaceTemplate
Definition: TemplateMetaProgramming.h:93
armarx::meta::IndexSequence
Definition: TemplateMetaProgramming.h:194