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 template<typename... Ts> using void_t = std::void_t<Ts...>;
27 
28 namespace 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  */
38 template<typename T>
39 struct debug_print;
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  */
51 template<typename... Types>
52 struct type_list {};
53 
54 namespace impl
55 {
56 
57 //
58 // head_of
59 //
60 template<typename T, typename... Rest>
61 struct head_of
62 {
63  using type = T;
64 };
65 
66 template<typename T>
67 struct 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  */
88 template<typename... L>
89 using head_of_t = typename impl::head_of<L...>::type;
90 
91 namespace impl
92 {
93 
94 //
95 // tail_of
96 //
97 template<typename T, typename... Rest>
98 struct tail_of
99 {
100  using type = type_list<Rest...>;
101 };
102 
103 template<typename L>
104 struct 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  */
126 template<typename... L>
127 using tail_of_t = typename impl::tail_of<L...>::type;
128 
129 namespace impl
130 {
131 
132 //
133 // put_front
134 //
135 template<typename T, typename Rest>
136 struct put_front;
137 
138 template<typename T, template<class...> class L, typename... Rest>
139 struct 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  */
162 template<typename T, typename Rest>
163 using put_front_t = typename impl::put_front<T, Rest>::type;
164 
165 namespace impl
166 {
167 
168 //
169 // rename
170 //
171 template<typename From, template<class...> class To>
172 struct rename;
173 
174 template<
175  template<class...> class From,
176  typename... Types,
177  template<class...> class To>
178 struct 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  */
200 template<typename From, template<class...> class To>
201 using rename_t = typename impl::rename<From, To>::type;
202 
203 namespace impl
204 {
205 
206 //
207 // transform
208 //
209 
210 template<
211  template<class...> class Transform_F,
212  typename To,
213  typename From >
214 struct transform;
215 
216 template<
217  template<class...> class Transform_F,
218  template<class...> class From,
219  typename... Sources,
220  template<class...> class To,
221  typename... 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 
231 template<
232  template<class...> class Transform_F,
233  template<class...> class From,
234  template<class...> class To,
235  typename... 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  */
256 template< template<class...> class Transform_F, typename From >
257 using transform_t = typename impl::transform<
258  Transform_F,
259  From,
260  type_list<>
261  >::type;
262 
263 namespace impl
264 {
265 
266 //
267 // all_of
268 //
269 template<
270  template<class...> class Predicate,
271  typename H,
272  typename... Tail >
273 struct all_of
274 {
275  static constexpr bool value = Predicate<H>::value &&
276  all_of<Predicate, Tail...>::value;
277 };
278 
279 template<
280  template<class...> class Predicate,
281  typename H >
282 struct 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.
290 template<
291  template<class...> class Predicate,
292  typename... 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  */
322 template< template<class...> class Predicate, typename... List >
323 constexpr bool all_of_v = impl::all_of<Predicate, List...>::value;
324 
325 } /* namespace metaprogramming */
326 
327 } /* namespace utils */
328 
329 } /* namespace restinio */
string_view_t from_string< string_view_t >(string_view_t s)
Get a value from string_view.
The basic building block: a type for representation of a type list.
std::enable_if< std::is_same< Parameter_Container, query_string_params_t >::value||std::is_same< Parameter_Container, router::route_params_t >::value, std::optional< Value_Type > >::type opt_value(const Parameter_Container &params, string_view_t key)
Gets the value of a parameter specified by key wrapped in std::optional<Value_Type> if parameter exis...
Definition: value_or.hpp:64
constexpr bool all_of_v
Applies the predicate to all types from the list and return true only if all types satisty that predi...