constant.hpp 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*!
  2. @file
  3. Forward declares `boost::hana::Constant`.
  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_CONCEPT_CONSTANT_HPP
  9. #define BOOST_HANA_FWD_CONCEPT_CONSTANT_HPP
  10. #include <boost/hana/config.hpp>
  11. BOOST_HANA_NAMESPACE_BEGIN
  12. //! @ingroup group-concepts
  13. //! @defgroup group-Constant Constant
  14. //! The `Constant` concept represents data that can be manipulated at
  15. //! compile-time.
  16. //!
  17. //! At its core, `Constant` is simply a generalization of the principle
  18. //! behind `std::integral_constant` to all types that can be constructed
  19. //! at compile-time, i.e. to all types with a `constexpr` constructor
  20. //! (also called [Literal types][1]). More specifically, a `Constant` is
  21. //! an object from which a `constexpr` value may be obtained (through the
  22. //! `value` method) regardless of the `constexpr`ness of the object itself.
  23. //!
  24. //! All `Constant`s must be somewhat equivalent, in the following sense.
  25. //! Let `C(T)` and `D(U)` denote the tags of `Constant`s holding objects
  26. //! of type `T` and `U`, respectively. Then, an object with tag `D(U)`
  27. //! must be convertible to an object with tag `C(T)` whenever `U` is
  28. //! convertible to `T`, as determined by `is_convertible`. The
  29. //! interpretation here is that a `Constant` is just a box holding
  30. //! an object of some type, and it should be possible to swap between
  31. //! boxes whenever the objects inside the boxes can be swapped.
  32. //!
  33. //! Because of this last requirement, one could be tempted to think that
  34. //! specialized "boxes" like `std::integral_constant` are prevented from
  35. //! being `Constant`s because they are not able to hold objects of any
  36. //! type `T` (`std::integral_constant` may only hold integral types).
  37. //! This is false; the requirement should be interpreted as saying that
  38. //! whenever `C(T)` is _meaningful_ (e.g. only when `T` is integral for
  39. //! `std::integral_constant`) _and_ there exists a conversion from `U`
  40. //! to `T`, then a conversion from `D(U)` to `C(T)` should also exist.
  41. //! The precise requirements for being a `Constant` are embodied in the
  42. //! following laws.
  43. //!
  44. //!
  45. //! Minimal complete definition
  46. //! ---------------------------
  47. //! `value` and `to`, satisfying the laws below.
  48. //!
  49. //!
  50. //! Laws
  51. //! ----
  52. //! Let `c` be an object of with tag `C`, which represents a `Constant`
  53. //! holding an object with tag `T`. The first law ensures that the value
  54. //! of the wrapped object is always a constant expression by requiring
  55. //! the following to be well-formed:
  56. //! @code
  57. //! constexpr auto x = hana::value<decltype(c)>();
  58. //! @endcode
  59. //!
  60. //! This means that the `value` function must return an object that can
  61. //! be constructed at compile-time. It is important to note how `value`
  62. //! only receives the type of the object and not the object itself.
  63. //! This is the core of the `Constant` concept; it means that the only
  64. //! information required to implement `value` must be stored in the _type_
  65. //! of its argument, and hence be available statically.
  66. //!
  67. //! The second law that must be satisfied ensures that `Constant`s are
  68. //! basically dumb boxes, which makes it possible to provide models for
  69. //! many concepts without much work from the user. The law simply asks
  70. //! for the following expression to be valid:
  71. //! @code
  72. //! to<C>(i)
  73. //! @endcode
  74. //! where, `i` is an _arbitrary_ `Constant` holding an internal value
  75. //! with a tag that can be converted to `T`, as determined by the
  76. //! `hana::is_convertible` metafunction. In other words, whenever `U` is
  77. //! convertible to `T`, a `Constant` holding a `U` is convertible to
  78. //! a `Constant` holding a `T`, if such a `Constant` can be created.
  79. //!
  80. //! Finally, the tag `C` must provide a nested `value_type` alias to `T`,
  81. //! which allows us to query the tag of the inner value held by objects
  82. //! with tag `C`. In other words, the following must be true for any
  83. //! object `c` with tag `C`:
  84. //! @code
  85. //! std::is_same<
  86. //! C::value_type,
  87. //! tag_of<decltype(hana::value(c))>::type
  88. //! >::value
  89. //! @endcode
  90. //!
  91. //!
  92. //! Refined concepts
  93. //! ----------------
  94. //! In certain cases, a `Constant` can automatically be made a model of
  95. //! another concept. In particular, if a `Constant` `C` is holding an
  96. //! object of tag `T`, and if `T` models a concept `X`, then `C` may
  97. //! in most cases model `X` by simply performing whatever operation is
  98. //! required on its underlying value, and then wrapping the result back
  99. //! in a `C`.
  100. //!
  101. //! More specifically, if a `Constant` `C` has an underlying value
  102. //! (`C::value_type`) which is a model of `Comparable`, `Orderable`,
  103. //! `Logical`, or `Monoid` up to `EuclideanRing`, then `C` must also
  104. //! be a model of those concepts. In other words, when `C::value_type`
  105. //! models one of the listed concepts, `C` itself must also model that
  106. //! concept. However, note that free models are provided for all of
  107. //! those concepts, so no additional work must be done.
  108. //!
  109. //! While it would be possible in theory to provide models for concepts
  110. //! like `Foldable` too, only a couple of concepts are useful to have as
  111. //! `Constant` in practice. Providing free models for the concepts listed
  112. //! above is useful because it allows various types of integral constants
  113. //! (`std::integral_constant`, `mpl::integral_c`, etc...) to easily have
  114. //! models for them just by defining the `Constant` concept.
  115. //!
  116. //! @remark
  117. //! An interesting observation is that `Constant` is actually the
  118. //! canonical embedding of the subcategory of `constexpr` things
  119. //! into the Hana category, which contains everything in this library.
  120. //! Hence, whatever is true in that subcategory is also true here, via
  121. //! this functor. This is why we can provide models of any concept that
  122. //! works on `constexpr` things for Constants, by simply passing them
  123. //! through that embedding.
  124. //!
  125. //!
  126. //! Concrete models
  127. //! ---------------
  128. //! `hana::integral_constant`
  129. //!
  130. //!
  131. //! Provided conversion to the tag of the underlying value
  132. //! ------------------------------------------------------
  133. //! Any `Constant` `c` holding an underlying value of tag `T` is
  134. //! convertible to any tag `U` such that `T` is convertible to `U`.
  135. //! Specifically, the conversion is equivalent to
  136. //! @code
  137. //! to<U>(c) == to<U>(value<decltype(c)>())
  138. //! @endcode
  139. //!
  140. //! Also, those conversions are marked as an embedding whenever the
  141. //! conversion of underlying types is an embedding. This is to allow
  142. //! Constants to inter-operate with `constexpr` objects easily:
  143. //! @code
  144. //! plus(int_c<1>, 1) == 2
  145. //! @endcode
  146. //!
  147. //! Strictly speaking, __this is sometimes a violation__ of what it means
  148. //! to be an embedding. Indeed, while there exists an embedding from any
  149. //! Constant to a `constexpr` object (since Constant is just the canonical
  150. //! inclusion), there is no embedding from a Constant to a runtime
  151. //! object since we would lose the ability to define the `value` method
  152. //! (the `constexpr`ness of the object would have been lost). Since there
  153. //! is no way to distinguish `constexpr` and non-`constexpr` objects based
  154. //! on their type, Hana has no way to know whether the conversion is to a
  155. //! `constexpr` object of not. In other words, the `to` method has no way
  156. //! to differentiate between
  157. //! @code
  158. //! constexpr int i = hana::to<int>(int_c<1>);
  159. //! @endcode
  160. //! which is an embedding, and
  161. //! @code
  162. //! int i = hana::to<int>(int_c<1>);
  163. //! @endcode
  164. //!
  165. //! which isn't. To be on the safer side, we could mark the conversion
  166. //! as not-an-embedding. However, if e.g. the conversion from
  167. //! `integral_constant_tag<int>` to `int` was not marked as an embedding,
  168. //! we would have to write `plus(to<int>(int_c<1>), 1)` instead of just
  169. //! `plus(int_c<1>, 1)`, which is cumbersome. Hence, the conversion is
  170. //! marked as an embedding, but this also means that code like
  171. //! @code
  172. //! int i = 1;
  173. //! plus(int_c<1>, i);
  174. //! @endcode
  175. //! will be considered valid, which implicitly loses the fact that
  176. //! `int_c<1>` is a Constant, and hence does not follow the usual rules
  177. //! for cross-type operations in Hana.
  178. //!
  179. //!
  180. //! Provided common data type
  181. //! -------------------------
  182. //! Because of the requirement that `Constant`s be interchangeable when
  183. //! their contents are compatible, two `Constant`s `A` and `B` will have
  184. //! a common data type whenever `A::value_type` and `B::value_type` have
  185. //! one. Their common data type is an unspecified `Constant` `C` such
  186. //! that `C::value_type` is exactly `common_t<A::value_type, B::value_type>`.
  187. //! A specialization of the `common` metafunction is provided for
  188. //! `Constant`s to reflect this.
  189. //!
  190. //! In the same vein, a common data type is also provided from any
  191. //! constant `A` to a type `T` such that `A::value_type` and `T` share
  192. //! a common type. The common type between `A` and `T` is obviously the
  193. //! common type between `A::value_type` and `T`. As explained above in
  194. //! the section on conversions, this is sometimes a violation of the
  195. //! definition of a common type, because there must be an embedding
  196. //! to the common type, which is not always the case. For the same
  197. //! reasons as explained above, this common type is still provided.
  198. //!
  199. //!
  200. //! [1]: http://en.cppreference.com/w/cpp/named_req/LiteralType
  201. template <typename C>
  202. struct Constant;
  203. BOOST_HANA_NAMESPACE_END
  204. #endif // !BOOST_HANA_FWD_CONCEPT_CONSTANT_HPP