]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*! |
2 | @file | |
3 | Forward declares `boost::hana::to` 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_CORE_TO_HPP | |
11 | #define BOOST_HANA_FWD_CORE_TO_HPP | |
12 | ||
13 | #include <boost/hana/config.hpp> | |
14 | ||
15 | ||
16 | BOOST_HANA_NAMESPACE_BEGIN | |
17 | //! @ingroup group-core | |
18 | //! Converts an object from one data type to another. | |
19 | //! | |
20 | //! `to` is a natural extension of the `static_cast` language construct to | |
21 | //! data types. Given a destination data type `To` and an object `x`, `to` | |
22 | //! creates a new object of data type `To` from `x`. Note, however, that | |
23 | //! `to` is not required to actually create a new object, and may return a | |
24 | //! reference to the original object (for example when trying to convert | |
25 | //! an object to its own data type). | |
26 | //! | |
27 | //! As a natural extension to `static_cast`, `to` provides a default | |
28 | //! behavior. For the purpose of what follows, let `To` be the destination | |
29 | //! data type and `From` be the data type of `x`, i.e. the source data type. | |
30 | //! Then, `to` has the following default behavior: | |
31 | //! 1. If the `To` and `From` data types are the same, then the object | |
32 | //! is forwarded as-is. | |
33 | //! 2. Otherwise, if `From` is convertible to `To` using `static_cast`, | |
34 | //! `x` is converted to `From` using `static_cast`. | |
35 | //! 3. Otherwise, calling `to<From>(x)` triggers a static assertion. | |
36 | //! | |
37 | //! However, `to` is a tag-dispatched function, which means that `to_impl` | |
38 | //! may be specialized in the `boost::hana` namespace to customize its | |
39 | //! behavior for arbitrary data types. Also note that `to` is tag-dispatched | |
40 | //! using both the `To` and the `From` data types, which means that `to_impl` | |
41 | //! is called as `to_impl<To, From>::%apply(x)`. Also note that some | |
42 | //! concepts provide conversions to or from their models. For example, | |
43 | //! any `Foldable` may be converted into a `Sequence`. This is achieved | |
44 | //! by specializing `to_impl<To, From>` whenever `To` is a `Sequence` and | |
45 | //! `From` is a `Foldable`. When such conversions are provided, they are | |
46 | //! documented in the source concept, in this case `Foldable`. | |
47 | //! | |
48 | //! | |
49 | //! Hana-convertibility | |
50 | //! ------------------- | |
51 | //! When an object `x` of data type `From` can be converted to a data type | |
52 | //! `To` using `to`, we say that `x` is Hana-convertible to the data type | |
53 | //! `To`. We also say that there is a Hana-conversion from `From` to `To`. | |
54 | //! This bit of terminology is useful to avoid mistaking the various kinds | |
55 | //! of conversions C++ offers. | |
56 | //! | |
57 | //! | |
58 | //! Embeddings | |
59 | //! ---------- | |
60 | //! As you might have seen by now, Hana uses algebraic and category- | |
61 | //! theoretical structures all around the place to help specify concepts | |
62 | //! in a rigorous way. These structures always have operations associated | |
63 | //! to them, which is why they are useful. The notion of embedding captures | |
64 | //! the idea of injecting a smaller structure into a larger one while | |
65 | //! preserving the operations of the structure. In other words, an | |
66 | //! embedding is an injective mapping that is also structure-preserving. | |
67 | //! Exactly what it means for a structure's operations to be preserved is | |
68 | //! left to explain by the documentation of each structure. For example, | |
69 | //! when we talk of a Monoid-embedding from a Monoid `A` to a Monoid `B`, | |
70 | //! we simply mean an injective transformation that preserves the identity | |
71 | //! and the associative operation, as documented in `Monoid`. | |
72 | //! | |
73 | //! But what does this have to do with the `to` function? Quite simply, | |
74 | //! the `to` function is a mapping between two data types, which will | |
75 | //! sometimes be some kind of structure, and it is sometimes useful to | |
76 | //! know whether such a mapping is well-behaved, i.e. lossless and | |
77 | //! structure preserving. The criterion for this conversion to be well- | |
78 | //! behaved is exactly that of being an embedding. To specify that a | |
79 | //! conversion is an embedding, simply use the `embedding` type as a | |
80 | //! base class of the corresponding `to_impl` specialization. Obviously, | |
81 | //! you should make sure the conversion is really an embedding, unless | |
82 | //! you want to shoot yourself in the foot. | |
83 | //! | |
84 | //! | |
85 | //! @tparam To | |
86 | //! The data type to which `x` should be converted. | |
87 | //! | |
88 | //! @param x | |
89 | //! The object to convert to the given data type. | |
90 | //! | |
91 | //! | |
92 | //! Example | |
93 | //! ------- | |
94 | //! @include example/core/convert/to.cpp | |
95 | #ifdef BOOST_HANA_DOXYGEN_INVOKED | |
96 | template <typename To> | |
97 | constexpr auto to = [](auto&& x) -> decltype(auto) { | |
98 | return tag-dispatched; | |
99 | }; | |
100 | #else | |
101 | template <typename To, typename From, typename = void> | |
102 | struct to_impl; | |
103 | ||
104 | template <typename To> | |
105 | struct to_t { | |
106 | template <typename X> | |
107 | constexpr decltype(auto) operator()(X&& x) const; | |
108 | }; | |
109 | ||
110 | template <typename To> | |
111 | constexpr to_t<To> to{}; | |
112 | #endif | |
113 | ||
114 | //! @ingroup group-core | |
115 | //! Returns whether there is a Hana-conversion from a data type to another. | |
116 | //! | |
117 | //! Specifically, `is_convertible<From, To>` is whether calling `to<To>` | |
118 | //! with an object of data type `From` would _not_ trigger a static | |
119 | //! assertion. | |
120 | //! | |
121 | //! | |
122 | //! Example | |
123 | //! ------- | |
124 | //! @include example/core/convert/is_convertible.cpp | |
125 | #ifdef BOOST_HANA_DOXYGEN_INVOKED | |
126 | template <typename From, typename To> | |
127 | struct is_convertible { see documentation }; | |
128 | #else | |
129 | template <typename From, typename To, typename = void> | |
130 | struct is_convertible; | |
131 | #endif | |
132 | ||
133 | //! @ingroup group-core | |
134 | //! Marks a conversion between data types as being an embedding. | |
135 | //! | |
136 | //! To mark a conversion between two data types `To` and `From` as | |
137 | //! an embedding, simply use `embedding<true>` (or simply `embedding<>`) | |
138 | //! as a base class of the corresponding `to_impl` specialization. | |
139 | //! If a `to_impl` specialization does not inherit `embedding<true>` | |
140 | //! or `embedding<>`, then it is not considered an embedding by the | |
141 | //! `is_embedded` metafunction. | |
142 | //! | |
143 | //! > #### Tip | |
144 | //! > The boolean template parameter is useful for marking a conversion | |
145 | //! > as an embedding only when some condition is satisfied. | |
146 | //! | |
147 | //! | |
148 | //! Example | |
149 | //! ------- | |
150 | //! @include example/core/convert/embedding.cpp | |
151 | template <bool = true> | |
152 | struct embedding { }; | |
153 | ||
154 | //! @ingroup group-core | |
155 | //! Returns whether a data type can be embedded into another data type. | |
156 | //! | |
157 | //! Given two data types `To` and `From`, `is_embedded<From, To>` returns | |
158 | //! whether `From` is convertible to `To`, and whether that conversion is | |
159 | //! also an embedding, as signaled by the `embedding` type. | |
160 | //! | |
161 | //! | |
162 | //! Example | |
163 | //! ------- | |
164 | //! @include example/core/convert/is_embedded.cpp | |
165 | #ifdef BOOST_HANA_DOXYGEN_INVOKED | |
166 | template <typename From, typename To> | |
167 | struct is_embedded { see documentation }; | |
168 | #else | |
169 | template <typename From, typename To, typename = void> | |
170 | struct is_embedded; | |
171 | #endif | |
172 | BOOST_HANA_NAMESPACE_END | |
173 | ||
174 | #endif // !BOOST_HANA_FWD_CORE_TO_HPP |