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