RESTinio
Loading...
Searching...
No Matches
metaprogramming.hpp
Go to the documentation of this file.
1/*
2 * RESTinio
3 */
4
5/*!
6 * \file
7 * \brief Various tools for C++ metaprogramming.
8 *
9 * \since
10 * v.0.6.1
11 */
12
13#pragma once
14
15#include <type_traits>
16
17namespace restinio
18{
19
20namespace utils
21{
22
24{
25
26template<typename... Ts> using void_t = std::void_t<Ts...>;
27
28namespace impl
29{
30
31//
32// debug_print
33//
34/*
35 * NOTE: this type is intended to be used just for debugging
36 * metaprogramming stuff. That is why it hasn't the definition.
37 */
38template<typename T>
40
41} /* namespace impl */
42
43//
44// type_list
45//
46/*!
47 * @brief The basic building block: a type for representation of a type list.
48 *
49 * @since v.0.6.1
50 */
51template<typename... Types>
52struct type_list {};
53
54namespace impl
55{
56
57//
58// head_of
59//
60template<typename T, typename... Rest>
61struct head_of
62{
63 using type = T;
64};
65
66template<typename T>
67struct head_of<T>
68{
69 using type = T;
70};
71
72} /* namespace impl */
73
74//
75// head_of_t
76//
77/*!
78 * @brief Metafunction to get the first item from a list of types.
79 *
80 * Usage example:
81 * @code
82 * using T = restinio::utils::metaprogramming::head_of_t<int, float, double>;
83 * static_assert(std::is_same_v<T, int>, "T isn't int");
84 * @endcode
85 *
86 * @since v.0.6.1
87 */
88template<typename... L>
89using head_of_t = typename impl::head_of<L...>::type;
90
91namespace impl
92{
93
94//
95// tail_of
96//
97template<typename T, typename... Rest>
98struct tail_of
99{
100 using type = type_list<Rest...>;
101};
102
103template<typename L>
104struct tail_of<L>
105{
106 using type = type_list<>;
107};
108
109} /* namespace impl */
110
111/*!
112 * @brief Metafunction to get the tail of a list of types in a form of type_list.
113 *
114 * Returns all types expect the first one. If input list of types contains
115 * just one type then `type_list<>` is returned.
116 *
117 * Usage example:
118 * @code
119 * using T = restinio::utils::metaprogramming::tail_of_t<int, float, double>;
120 * static_assert(std::is_same_v<T,
121 * restinio::utils::metaprogramming::typelist<float, double> >, "!Ok");
122 * @endcode
123 *
124 * @since v.0.6.1
125 */
126template<typename... L>
127using tail_of_t = typename impl::tail_of<L...>::type;
128
129namespace impl
130{
131
132//
133// put_front
134//
135template<typename T, typename Rest>
137
138template<typename T, template<class...> class L, typename... Rest>
139struct put_front< T, L<Rest...> >
140{
141 using type = L<T, Rest...>;
142};
143
144} /* namespace impl */
145
146//
147// put_front_t
148//
149/*!
150 * @brief Metafunction to insert a type to the front of a type_list.
151 *
152 * Usage example:
153 * @code
154 * using namespace restinio::utils::metaprogramming;
155 *
156 * using T = put_front_t<int, type_list<float, double>>;
157 * static_assert(std::is_same_v<T, typelist<int, float, double> >, "!Ok");
158 * @endcode
159 *
160 * @since v.0.6.1
161 */
162template<typename T, typename Rest>
163using put_front_t = typename impl::put_front<T, Rest>::type;
164
165namespace impl
166{
167
168//
169// rename
170//
171template<typename From, template<class...> class To>
172struct rename;
173
174template<
175 template<class...> class From,
176 typename... Types,
177 template<class...> class To>
178struct rename<From<Types...>, To>
179{
180 using type = To<Types...>;
181};
182
183} /* namespace impl */
184
185//
186// rename_t
187//
188/*!
189 * @brief Allows to pass all template arguments from one type to another.
190 *
191 * Usage example:
192 * @code
193 * using namespace restinio::utils::metaprogramming;
194 * using T = rename_t<typelist<int, float, double>, std::tuple>;
195 * static_assert(std::is_same_v<T, std::tuble<int, float, double>>, "!Ok");
196 * @endcode
197 *
198 * @since v.0.6.1
199 */
200template<typename From, template<class...> class To>
201using rename_t = typename impl::rename<From, To>::type;
202
203namespace impl
204{
205
206//
207// transform
208//
209
210template<
211 template<class...> class Transform_F,
212 typename To,
213 typename From >
215
216template<
217 template<class...> class Transform_F,
218 template<class...> class From,
219 typename... Sources,
220 template<class...> class To,
221 typename... Results >
222struct transform< Transform_F, From<Sources...>, To<Results...> >
223{
224 using type = typename transform<
225 Transform_F,
226 tail_of_t<Sources...>,
227 To<Results..., typename Transform_F< head_of_t<Sources...> >::type>
228 >::type;
229};
230
231template<
232 template<class...> class Transform_F,
233 template<class...> class From,
234 template<class...> class To,
235 typename... Results >
236struct transform< Transform_F, From<>, To<Results...> >
237{
238 using type = To<Results...>;
239};
240
241} /* namespace impl */
242
243/*!
244 * @brief Applies a specified meta-function to every item from
245 * a specified type-list and return a new type-list.
246 *
247 * Usage example:
248 * @code
249 * using namespace restinio::utils::metaprogramming;
250 * using T = transform_t<std::decay, type_list<int, char &, const long &>>;
251 * static_assert(std::is_same<T, type_list<int, char, long>>::value, "!Ok");
252 * @endcode
253 *
254 * @since v.0.6.6
255 */
256template< template<class...> class Transform_F, typename From >
257using transform_t = typename impl::transform<
258 Transform_F,
259 From,
260 type_list<>
261 >::type;
262
263namespace impl
264{
265
266//
267// all_of
268//
269template<
270 template<class...> class Predicate,
271 typename H,
272 typename... Tail >
273struct all_of
274{
275 static constexpr bool value = Predicate<H>::value &&
276 all_of<Predicate, Tail...>::value;
277};
278
279template<
280 template<class...> class Predicate,
281 typename H >
282struct all_of< Predicate, H >
283{
284 static constexpr bool value = Predicate<H>::value;
285};
286
287// Specialization for the case when types are represented as type_list.
288//
289// Since v.0.6.6.
290template<
291 template<class...> class Predicate,
292 typename... Types >
293struct all_of< Predicate, type_list<Types...> >
294{
295 static constexpr bool value = all_of<Predicate, Types...>::value;
296};
297
298} /* namespace impl */
299
300//
301// all_of
302//
303/*!
304 * @brief Applies the predicate to all types from the list and
305 * return true only if all types satisty that predicate.
306 *
307 * Usage example:
308 * @code
309 * using namespace restinio::utils::metaprogramming;
310 * static_assert(all_of_v<std::is_integral, int, long, unsigned short>, "!Ok");
311 * @endcode
312 *
313 * Since v.0.6.6 can be used with type_list:
314 * @code
315 * using namespace restinio::utils::metaprogramming;
316 * static_assert(all_of_v<std::is_integral,
317 * transform_t<std::decay, type_list<int &, long &, unsigned short&>>>, "!Ok");
318 * @endcode
319 *
320 * @since v.0.6.1
321 */
322template< template<class...> class Predicate, typename... List >
323constexpr bool all_of_v = impl::all_of<Predicate, List...>::value;
324
325} /* namespace metaprogramming */
326
327} /* namespace utils */
328
329} /* namespace restinio */
typename impl::put_front< T, Rest >::type put_front_t
Metafunction to insert a type to the front of a type_list.
constexpr bool all_of_v
Applies the predicate to all types from the list and return true only if all types satisty that predi...
typename impl::head_of< L... >::type head_of_t
Metafunction to get the first item from a list of types.
typename impl::transform< Transform_F, From, type_list<> >::type transform_t
Applies a specified meta-function to every item from a specified type-list and return a new type-list...
typename impl::rename< From, To >::type rename_t
Allows to pass all template arguments from one type to another.
typename impl::tail_of< L... >::type tail_of_t
Metafunction to get the tail of a list of types in a form of type_list.
typename transform< Transform_F, tail_of_t< Sources... >, To< Results..., typename Transform_F< head_of_t< Sources... > >::type > >::type type
The basic building block: a type for representation of a type list.