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