type.hpp 19 KB

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