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
30namespace 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>
89
90 template <class T, template <class...> class... Templates>
91 static constexpr bool IsInstanceOfAnyV = (IsInstanceOf<Templates, T>::value || ...);
92
94 static_assert(
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>
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>
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
242namespace 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>
254 struct MakeIndexSequence;
255
256 template <>
258 {
259 };
260
261 template <>
263 {
264 };
265
266 template <std::size_t N>
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
288namespace 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>
298} // namespace armarx::meta
299
300namespace 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
330namespace 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
357namespace 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
363namespace 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
T0 first_type
Get the type of the first element of a template parameter pack.
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.
typename detail::MakeIndexRange< Lo, Hi >::type MakeIndexRange
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.
T1 second_type
Get the type of the second element of a template parameter pack.
typename RemoveRvalueReference< T >::type RemoveRvalueReferenceT
typename detail::MakeIndexSequence< N >::type MakeIndexSequence
T2 third_type
Get the type of the third element of a template parameter pack.
void void_t
Helper for sfinae (is added in c++17)
MakeIndexSequence< sizeof...(Ts)> MakeIndexSequenceFor
detail::DecayAll< typename std::decay< T >::type > DecayAll
Similar to std::decay but also decays ptr and array.
Can be used to determine if T has an at method accepting a type of IdxT.
Can be used to determine if there is an overload for std::to_string for a type T.
typename std::decay< typename std::tuple_element< n, std::tuple< T0, Ts... > >::type >::type type
Removes rvalue ref from a type.
Whether a type T is the instance of a given template Template.
Traits about templates taking only types as parameters.
typename std::decay< T >::type type