]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/hana/include/boost/hana/fwd/type.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / hana / include / boost / hana / fwd / type.hpp
1 /*!
2 @file
3 Forward declares `boost::hana::type` and related utilities.
4
5 @copyright Louis Dionne 2013-2016
6 Distributed under the Boost Software License, Version 1.0.
7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
8 */
9
10 #ifndef BOOST_HANA_FWD_TYPE_HPP
11 #define BOOST_HANA_FWD_TYPE_HPP
12
13 #include <boost/hana/config.hpp>
14 #include <boost/hana/fwd/core/make.hpp>
15
16
17 BOOST_HANA_NAMESPACE_BEGIN
18 //! Base class of `hana::type`; used for pattern-matching.
19 //! @relates hana::type
20 //!
21 //! Example
22 //! -------
23 //! @include example/type/basic_type.cpp
24 template <typename T>
25 struct basic_type;
26
27 //! @ingroup group-datatypes
28 //! C++ type in value-level representation.
29 //!
30 //! A `type` is a special kind of object representing a C++ type like
31 //! `int`, `void`, `std::vector<float>` or anything else you can imagine.
32 //!
33 //! This page explains how `type`s work at a low level. To gain
34 //! intuition about type-level metaprogramming in Hana, you should
35 //! read the [tutorial section](@ref tutorial-type) on type-level
36 //! computations.
37 //!
38 //!
39 //! @note
40 //! For subtle reasons having to do with ADL, the actual representation of
41 //! `hana::type` is implementation-defined. In particular, `hana::type`
42 //! may be a dependent type, so one should not attempt to do pattern
43 //! matching on it. However, one can assume that `hana::type` _inherits_
44 //! from `hana::basic_type`, which can be useful when declaring overloaded
45 //! functions:
46 //! @code
47 //! template <typename T>
48 //! void f(hana::basic_type<T>) {
49 //! // do something with T
50 //! }
51 //! @endcode
52 //!
53 //!
54 //! @anchor type_lvalues_and_rvalues
55 //! Lvalues and rvalues
56 //! -------------------
57 //! When storing `type`s in heterogeneous containers, some algorithms
58 //! will return references to those objects. Since we are primarily
59 //! interested in accessing their nested `::%type`, receiving a reference
60 //! is undesirable; we would end up trying to fetch the nested `::%type`
61 //! inside a reference type, which is a compilation error:
62 //! @code
63 //! auto ts = make_tuple(type_c<int>, type_c<char>);
64 //! using T = decltype(ts[0_c])::type; // error: 'ts[0_c]' is a reference!
65 //! @endcode
66 //!
67 //! For this reason, `type`s provide an overload of the unary `+`
68 //! operator that can be used to turn a lvalue into a rvalue. So when
69 //! using a result which might be a reference to a `type` object, one
70 //! can use `+` to make sure a rvalue is obtained before fetching its
71 //! nested `::%type`:
72 //! @code
73 //! auto ts = make_tuple(type_c<int>, type_c<char>);
74 //! using T = decltype(+ts[0_c])::type; // ok: '+ts[0_c]' is an rvalue
75 //! @endcode
76 //!
77 //!
78 //! Modeled concepts
79 //! ----------------
80 //! 1. `Comparable`\n
81 //! Two types are equal if and only if they represent the same C++ type.
82 //! Hence, equality is equivalent to the `std::is_same` type trait.
83 //! @include example/type/comparable.cpp
84 //!
85 //! 2. `Hashable`\n
86 //! The hash of a type is just that type itself. In other words, `hash`
87 //! is the identity function on `hana::type`s.
88 //! @include example/type/hashable.cpp
89 #ifdef BOOST_HANA_DOXYGEN_INVOKED
90 template <typename T>
91 struct type {
92 //! Returns rvalue of self.
93 //! See @ref type_lvalues_and_rvalues "description".
94 constexpr auto operator+() const;
95
96 //! Equivalent to `hana::equal`
97 template <typename X, typename Y>
98 friend constexpr auto operator==(X&& x, Y&& y);
99
100 //! Equivalent to `hana::not_equal`
101 template <typename X, typename Y>
102 friend constexpr auto operator!=(X&& x, Y&& y);
103 };
104 #else
105 template <typename T>
106 struct type_impl;
107
108 template <typename T>
109 using type = typename type_impl<T>::_;
110 #endif
111
112 //! Tag representing `hana::type`.
113 //! @relates hana::type
114 struct type_tag { };
115
116 //! Creates an object representing the C++ type `T`.
117 //! @relates hana::type
118 template <typename T>
119 constexpr type<T> type_c{};
120
121 //! `decltype` keyword, lifted to Hana.
122 //! @relates hana::type
123 //!
124 //! @deprecated
125 //! The semantics of `decltype_` can be confusing, and `hana::typeid_`
126 //! should be preferred instead. `decltype_` may be removed in the next
127 //! major version of the library.
128 //!
129 //! `decltype_` is somewhat equivalent to `decltype` in that it returns
130 //! the type of an object, except it returns it as a `hana::type` which
131 //! is a first-class citizen of Hana instead of a raw C++ type.
132 //! Specifically, given an object `x`, `decltype_` satisfies
133 //! @code
134 //! decltype_(x) == type_c<decltype(x) with references stripped>
135 //! @endcode
136 //!
137 //! As you can see, `decltype_` will strip any reference from the
138 //! object's actual type. The reason for doing so is explained below.
139 //! However, any `cv`-qualifiers will be retained. Also, when given a
140 //! `hana::type`, `decltype_` is just the identity function. Hence,
141 //! for any C++ type `T`,
142 //! @code
143 //! decltype_(type_c<T>) == type_c<T>
144 //! @endcode
145 //!
146 //! In conjunction with the way `metafunction` & al. are specified, this
147 //! behavior makes it easier to interact with both types and values at
148 //! the same time. However, it does make it impossible to create a `type`
149 //! containing another `type` with `decltype_`. In other words, it is
150 //! not possible to create a `type_c<decltype(type_c<T>)>` with this
151 //! utility, because `decltype_(type_c<T>)` would be just `type_c<T>`
152 //! instead of `type_c<decltype(type_c<T>)>`. This use case is assumed
153 //! to be rare and a hand-coded function can be used if this is needed.
154 //!
155 //!
156 //! ### Rationale for stripping the references
157 //! The rules for template argument deduction are such that a perfect
158 //! solution that always matches `decltype` is impossible. Hence, we
159 //! have to settle on a solution that's good and and consistent enough
160 //! for our needs. One case where matching `decltype`'s behavior is
161 //! impossible is when the argument is a plain, unparenthesized variable
162 //! or function parameter. In that case, `decltype_`'s argument will be
163 //! deduced as a reference to that variable, but `decltype` would have
164 //! given us the actual type of that variable, without references. Also,
165 //! given the current definition of `metafunction` & al., it would be
166 //! mostly useless if `decltype_` could return a reference, because it
167 //! is unlikely that `F` expects a reference in its simplest use case:
168 //! @code
169 //! int i = 0;
170 //! auto result = metafunction<F>(i);
171 //! @endcode
172 //!
173 //! Hence, always discarding references seems to be the least painful
174 //! solution.
175 //!
176 //!
177 //! Example
178 //! -------
179 //! @include example/type/decltype.cpp
180 #ifdef BOOST_HANA_DOXYGEN_INVOKED
181 constexpr auto decltype_ = see documentation;
182 #else
183 struct decltype_t {
184 template <typename T>
185 constexpr auto operator()(T&&) const;
186 };
187
188 constexpr decltype_t decltype_{};
189 #endif
190
191 //! Returns a `hana::type` representing the type of a given object.
192 //! @relates hana::type
193 //!
194 //! `hana::typeid_` is somewhat similar to `typeid` in that it returns
195 //! something that represents the type of an object. However, what
196 //! `typeid` returns represent the _runtime_ type of the object, while
197 //! `hana::typeid_` returns the _static_ type of the object. Specifically,
198 //! given an object `x`, `typeid_` satisfies
199 //! @code
200 //! typeid_(x) == type_c<decltype(x) with ref and cv-qualifiers stripped>
201 //! @endcode
202 //!
203 //! As you can see, `typeid_` strips any reference and cv-qualifier from
204 //! the object's actual type. The reason for doing so is that it faithfully
205 //! models how the language's `typeid` behaves with respect to reference
206 //! and cv-qualifiers, and it also turns out to be the desirable behavior
207 //! most of the time. Also, when given a `hana::type`, `typeid_` is just
208 //! the identity function. Hence, for any C++ type `T`,
209 //! @code
210 //! typeid_(type_c<T>) == type_c<T>
211 //! @endcode
212 //!
213 //! In conjunction with the way `metafunction` & al. are specified, this
214 //! behavior makes it easier to interact with both types and values at
215 //! the same time. However, it does make it impossible to create a `type`
216 //! containing another `type` using `typeid_`. This use case is assumed
217 //! to be rare and a hand-coded function can be used if this is needed.
218 //!
219 //!
220 //! Example
221 //! -------
222 //! @include example/type/typeid.cpp
223 #ifdef BOOST_HANA_DOXYGEN_INVOKED
224 constexpr auto typeid_ = see documentation;
225 #else
226 struct typeid_t {
227 template <typename T>
228 constexpr auto operator()(T&&) const;
229 };
230
231 constexpr typeid_t typeid_{};
232 #endif
233
234 #ifdef BOOST_HANA_DOXYGEN_INVOKED
235 //! Equivalent to `decltype_`, provided for convenience.
236 //! @relates hana::type
237 //!
238 //!
239 //! Example
240 //! -------
241 //! @include example/type/make.cpp
242 template <>
243 constexpr auto make<type_tag> = hana::decltype_;
244 #endif
245
246 //! Equivalent to `make<type_tag>`, provided for convenience.
247 //! @relates hana::type
248 //!
249 //!
250 //! Example
251 //! -------
252 //! @include example/type/make.cpp
253 constexpr auto make_type = hana::make<type_tag>;
254
255 //! `sizeof` keyword, lifted to Hana.
256 //! @relates hana::type
257 //!
258 //! `sizeof_` is somewhat equivalent to `sizeof` in that it returns the
259 //! size of an expression or type, but it takes an arbitrary expression
260 //! or a `hana::type` and returns its size as an `integral_constant`.
261 //! Specifically, given an expression `expr`, `sizeof_` satisfies
262 //! @code
263 //! sizeof_(expr) == size_t<sizeof(decltype(expr) with references stripped)>
264 //! @endcode
265 //!
266 //! However, given a `type`, `sizeof_` will simply fetch the size
267 //! of the C++ type represented by that object. In other words,
268 //! @code
269 //! sizeof_(type_c<T>) == size_t<sizeof(T)>
270 //! @endcode
271 //!
272 //! The behavior of `sizeof_` is consistent with that of `decltype_`.
273 //! In particular, see `decltype_`'s documentation to understand why
274 //! references are always stripped by `sizeof_`.
275 //!
276 //!
277 //! Example
278 //! -------
279 //! @include example/type/sizeof.cpp
280 #ifdef BOOST_HANA_DOXYGEN_INVOKED
281 constexpr auto sizeof_ = [](auto&& x) {
282 using T = typename decltype(hana::decltype_(x))::type;
283 return hana::size_c<sizeof(T)>;
284 };
285 #else
286 struct sizeof_t {
287 template <typename T>
288 constexpr auto operator()(T&&) const;
289 };
290
291 constexpr sizeof_t sizeof_{};
292 #endif
293
294 //! `alignof` keyword, lifted to Hana.
295 //! @relates hana::type
296 //!
297 //! `alignof_` is somewhat equivalent to `alignof` in that it returns the
298 //! alignment required by any instance of a type, but it takes a `type`
299 //! and returns its alignment as an `integral_constant`. Like `sizeof`
300 //! which works for expressions and type-ids, `alignof_` can also be
301 //! called on an arbitrary expression. Specifically, given an expression
302 //! `expr` and a C++ type `T`, `alignof_` satisfies
303 //! @code
304 //! alignof_(expr) == size_t<alignof(decltype(expr) with references stripped)>
305 //! alignof_(type_c<T>) == size_t<alignof(T)>
306 //! @endcode
307 //!
308 //! The behavior of `alignof_` is consistent with that of `decltype_`.
309 //! In particular, see `decltype_`'s documentation to understand why
310 //! references are always stripped by `alignof_`.
311 //!
312 //!
313 //! Example
314 //! -------
315 //! @include example/type/alignof.cpp
316 #ifdef BOOST_HANA_DOXYGEN_INVOKED
317 constexpr auto alignof_ = [](auto&& x) {
318 using T = typename decltype(hana::decltype_(x))::type;
319 return hana::size_c<alignof(T)>;
320 };
321 #else
322 struct alignof_t {
323 template <typename T>
324 constexpr auto operator()(T&&) const;
325 };
326
327 constexpr alignof_t alignof_{};
328 #endif
329
330 //! Checks whether a SFINAE-friendly expression is valid.
331 //! @relates hana::type
332 //!
333 //! Given a SFINAE-friendly function, `is_valid` returns whether the
334 //! function call is valid with the given arguments. Specifically, given
335 //! a function `f` and arguments `args...`,
336 //! @code
337 //! is_valid(f, args...) == whether f(args...) is valid
338 //! @endcode
339 //!
340 //! The result is returned as a compile-time `Logical`. Furthermore,
341 //! `is_valid` can be used in curried form as follows:
342 //! @code
343 //! is_valid(f)(args...)
344 //! @endcode
345 //!
346 //! This syntax makes it easy to create functions that check the validity
347 //! of a generic expression on any given argument(s).
348 //!
349 //! @warning
350 //! To check whether calling a nullary function `f` is valid, one should
351 //! use the `is_valid(f)()` syntax. Indeed, `is_valid(f /* no args */)`
352 //! will be interpreted as the currying of `is_valid` to `f` rather than
353 //! the application of `is_valid` to `f` and no arguments.
354 //!
355 //!
356 //! Example
357 //! -------
358 //! @include example/type/is_valid.cpp
359 #ifdef BOOST_HANA_DOXYGEN_INVOKED
360 constexpr auto is_valid = [](auto&& f) {
361 return [](auto&& ...args) {
362 return whether f(args...) is a valid expression;
363 };
364 };
365 #else
366 struct is_valid_t {
367 template <typename F>
368 constexpr auto operator()(F&&) const;
369
370 template <typename F, typename ...Args>
371 constexpr auto operator()(F&&, Args&&...) const;
372 };
373
374 constexpr is_valid_t is_valid{};
375 #endif
376
377 //! Lift a template to a Metafunction.
378 //! @ingroup group-Metafunction
379 //!
380 //! Given a template class or template alias `f`, `template_<f>` is a
381 //! `Metafunction` satisfying
382 //! @code
383 //! template_<f>(type_c<x>...) == type_c<f<x...>>
384 //! decltype(template_<f>)::apply<x...>::type == f<x...>
385 //! @endcode
386 //!
387 //! @note
388 //! `template_` can't be SFINAE-friendly right now because of
389 //! [Core issue 1430][1].
390 //!
391 //!
392 //! Example
393 //! -------
394 //! @include example/type/template.cpp
395 //!
396 //! [1]: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1430
397 #ifdef BOOST_HANA_DOXYGEN_INVOKED
398 template <template <typename ...> class F>
399 constexpr auto template_ = [](basic_type<T>...) {
400 return hana::type_c<F<T...>>;
401 };
402 #else
403 template <template <typename ...> class F>
404 struct template_t;
405
406 template <template <typename ...> class F>
407 constexpr template_t<F> template_{};
408 #endif
409
410 //! Lift a MPL-style metafunction to a Metafunction.
411 //! @ingroup group-Metafunction
412 //!
413 //! Given a MPL-style metafunction, `metafunction<f>` is a `Metafunction`
414 //! satisfying
415 //! @code
416 //! metafunction<f>(type_c<x>...) == type_c<f<x...>::type>
417 //! decltype(metafunction<f>)::apply<x...>::type == f<x...>::type
418 //! @endcode
419 //!
420 //!
421 //! Example
422 //! -------
423 //! @include example/type/metafunction.cpp
424 #ifdef BOOST_HANA_DOXYGEN_INVOKED
425 template <template <typename ...> class F>
426 constexpr auto metafunction = [](basic_type<T>...) {
427 return hana::type_c<typename F<T...>::type>;
428 };
429 #else
430 template <template <typename ...> class f>
431 struct metafunction_t;
432
433 template <template <typename ...> class f>
434 constexpr metafunction_t<f> metafunction{};
435 #endif
436
437 //! Lift a MPL-style metafunction class to a Metafunction.
438 //! @ingroup group-Metafunction
439 //!
440 //! Given a MPL-style metafunction class, `metafunction_class<f>` is a
441 //! `Metafunction` satisfying
442 //! @code
443 //! metafunction_class<f>(type_c<x>...) == type_c<f::apply<x...>::type>
444 //! decltype(metafunction_class<f>)::apply<x...>::type == f::apply<x...>::type
445 //! @endcode
446 //!
447 //!
448 //! Example
449 //! -------
450 //! @include example/type/metafunction_class.cpp
451 #ifdef BOOST_HANA_DOXYGEN_INVOKED
452 template <typename F>
453 constexpr auto metafunction_class = [](basic_type<T>...) {
454 return hana::type_c<typename F::template apply<T...>::type>;
455 };
456 #else
457 template <typename F>
458 struct metafunction_class_t
459 : metafunction_t<F::template apply>
460 { };
461
462 template <typename F>
463 constexpr metafunction_class_t<F> metafunction_class{};
464 #endif
465
466 //! Turn a `Metafunction` into a function taking `type`s and returning a
467 //! default-constructed object.
468 //! @ingroup group-Metafunction
469 //!
470 //! Given a `Metafunction` `f`, `integral` returns a new `Metafunction`
471 //! that default-constructs an object of the type returned by `f`. More
472 //! specifically, the following holds:
473 //! @code
474 //! integral(f)(t...) == decltype(f(t...))::type{}
475 //! @endcode
476 //!
477 //! The principal use case for `integral` is to transform `Metafunction`s
478 //! returning a type that inherits from a meaningful base like
479 //! `std::integral_constant` into functions returning e.g. a
480 //! `hana::integral_constant`.
481 //!
482 //! @note
483 //! - This is not a `Metafunction` because it does not return a `type`.
484 //! As such, it would not make sense to make `decltype(integral(f))`
485 //! a MPL metafunction class like the usual `Metafunction`s are.
486 //!
487 //! - When using `integral` with metafunctions returning
488 //! `std::integral_constant`s, don't forget to include the
489 //! boost/hana/ext/std/integral_constant.hpp header to ensure
490 //! Hana can interoperate with the result.
491 //!
492 //!
493 //! Example
494 //! -------
495 //! @include example/type/integral.cpp
496 #ifdef BOOST_HANA_DOXYGEN_INVOKED
497 constexpr auto integral = [](auto f) {
498 return [](basic_type<T>...) {
499 return decltype(f)::apply<T...>::type{};
500 };
501 };
502 #else
503 template <typename F>
504 struct integral_t;
505
506 struct make_integral_t {
507 template <typename F>
508 constexpr integral_t<F> operator()(F const&) const
509 { return {}; }
510 };
511
512 constexpr make_integral_t integral{};
513 #endif
514
515 //! Alias to `integral(metafunction<F>)`, provided for convenience.
516 //! @ingroup group-Metafunction
517 //!
518 //!
519 //! Example
520 //! -------
521 //! @include example/type/trait.cpp
522 template <template <typename ...> class F>
523 constexpr auto trait = hana::integral(hana::metafunction<F>);
524 BOOST_HANA_NAMESPACE_END
525
526 #endif // !BOOST_HANA_FWD_TYPE_HPP