]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*! |
2 | @file | |
3 | Forward declares `boost::hana::map`. | |
4 | ||
b32b8144 | 5 | @copyright Louis Dionne 2013-2017 |
7c673cae FG |
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_MAP_HPP | |
11 | #define BOOST_HANA_FWD_MAP_HPP | |
12 | ||
13 | #include <boost/hana/config.hpp> | |
14 | #include <boost/hana/fwd/core/to.hpp> | |
15 | #include <boost/hana/fwd/core/make.hpp> | |
16 | #include <boost/hana/fwd/erase_key.hpp> | |
17 | #include <boost/hana/fwd/insert.hpp> | |
18 | #include <boost/hana/fwd/keys.hpp> | |
19 | ||
20 | ||
1e59de90 | 21 | namespace boost { namespace hana { |
b32b8144 FG |
22 | //! Tag representing `hana::map`s. |
23 | //! @relates hana::map | |
24 | struct map_tag { }; | |
25 | ||
26 | namespace detail { | |
27 | template <typename ...Pairs> | |
28 | struct make_map_type; | |
29 | } | |
30 | ||
7c673cae FG |
31 | //! @ingroup group-datatypes |
32 | //! Basic associative container requiring unique, `Comparable` and | |
33 | //! `Hashable` keys. | |
34 | //! | |
35 | //! The order of the elements of the map is unspecified. Also, all the | |
36 | //! keys must be `Hashable`, and any two keys with equal hashes must be | |
37 | //! `Comparable` with each other at compile-time. | |
38 | //! | |
92f5a8d4 TL |
39 | //! @note |
40 | //! The actual representation of a `hana::map` is an implementation | |
b32b8144 FG |
41 | //! detail. As such, one should not assume anything more than what is |
42 | //! explicitly documented as being part of the interface of a map, | |
43 | //! such as: | |
44 | //! - the presence of additional constructors | |
45 | //! - the presence of additional assignment operators | |
46 | //! - the fact that `hana::map<Pairs...>` is, or is not, a dependent type | |
92f5a8d4 | 47 | //! . |
b32b8144 FG |
48 | //! In particular, the last point is very important; `hana::map<Pairs...>` |
49 | //! is basically equivalent to | |
50 | //! @code | |
51 | //! decltype(hana::make_pair(std::declval<Pairs>()...)) | |
52 | //! @endcode | |
53 | //! which is not something that can be pattern-matched on during template | |
92f5a8d4 TL |
54 | //! argument deduction, for example. More details [in the tutorial] |
55 | //! (@ref tutorial-containers-types). | |
7c673cae FG |
56 | //! |
57 | //! | |
58 | //! Modeled concepts | |
59 | //! ---------------- | |
60 | //! 1. `Comparable`\n | |
61 | //! Two maps are equal iff all their keys are equal and are associated | |
62 | //! to equal values. | |
63 | //! @include example/map/comparable.cpp | |
64 | //! | |
65 | //! 2. `Searchable`\n | |
66 | //! A map can be searched by its keys with a predicate yielding a | |
67 | //! compile-time `Logical`. Also note that `operator[]` can be used | |
68 | //! instead of `at_key`. | |
69 | //! @include example/map/searchable.cpp | |
70 | //! | |
71 | //! 3. `Foldable`\n | |
72 | //! Folding a map is equivalent to folding a list of the key/value pairs | |
73 | //! it contains. In particular, since that list is not guaranteed to be | |
74 | //! in any specific order, folding a map with an operation that is not | |
75 | //! both commutative and associative will yield non-deterministic behavior. | |
76 | //! @include example/map/foldable.cpp | |
77 | //! | |
78 | //! | |
79 | //! Conversion from any `Foldable` | |
80 | //! ------------------------------ | |
81 | //! Any `Foldable` of `Product`s can be converted to a `hana::map` with | |
82 | //! `hana::to<hana::map_tag>` or, equivalently, `hana::to_map`. If the | |
83 | //! `Foldable` contains duplicate keys, only the value associated to the | |
84 | //! first occurence of each key is kept. | |
85 | //! @include example/map/to.cpp | |
b32b8144 FG |
86 | //! |
87 | //! | |
88 | //! Example | |
89 | //! ------- | |
90 | //! @include example/map/map.cpp | |
7c673cae | 91 | #ifdef BOOST_HANA_DOXYGEN_INVOKED |
b32b8144 | 92 | template <typename ...Pairs> |
7c673cae FG |
93 | struct map { |
94 | //! Default-construct a map. This constructor only exists when all the | |
95 | //! elements of the map are default-constructible. | |
96 | constexpr map() = default; | |
97 | ||
98 | //! Copy-construct a map from another map. This constructor only | |
99 | //! exists when all the elements of the map are copy-constructible. | |
100 | constexpr map(map const& other) = default; | |
101 | ||
102 | //! Move-construct a map from another map. This constructor only | |
103 | //! exists when all the elements of the map are move-constructible. | |
104 | constexpr map(map&& other) = default; | |
105 | ||
b32b8144 FG |
106 | //! Construct the map from the provided pairs. `P...` must be pairs of |
107 | //! the same type (modulo ref and cv-qualifiers), and in the same order, | |
108 | //! as those appearing in `Pairs...`. The pairs provided to this | |
109 | //! constructor are emplaced into the map's storage using perfect | |
110 | //! forwarding. | |
111 | template <typename ...P> | |
112 | explicit constexpr map(P&& ...pairs); | |
113 | ||
114 | //! Assign a map to another map __with the exact same type__. Only | |
115 | //! exists when all the elements of the map are copy-assignable. | |
116 | constexpr map& operator=(map const& other); | |
117 | ||
118 | //! Move-assign a map to another map __with the exact same type__. | |
119 | //! Only exists when all the elements of the map are move-assignable. | |
120 | constexpr map& operator=(map&& other); | |
121 | ||
7c673cae FG |
122 | //! Equivalent to `hana::equal` |
123 | template <typename X, typename Y> | |
124 | friend constexpr auto operator==(X&& x, Y&& y); | |
125 | ||
126 | //! Equivalent to `hana::not_equal` | |
127 | template <typename X, typename Y> | |
128 | friend constexpr auto operator!=(X&& x, Y&& y); | |
129 | ||
130 | //! Equivalent to `hana::at_key` | |
131 | template <typename Key> | |
132 | constexpr decltype(auto) operator[](Key&& key); | |
133 | }; | |
134 | #else | |
b32b8144 FG |
135 | template <typename ...Pairs> |
136 | using map = typename detail::make_map_type<Pairs...>::type; | |
7c673cae FG |
137 | #endif |
138 | ||
7c673cae FG |
139 | //! Function object for creating a `hana::map`. |
140 | //! @relates hana::map | |
141 | //! | |
142 | //! Given zero or more `Product`s representing key/value associations, | |
143 | //! `make<map_tag>` returns a `hana::map` associating these keys to these | |
144 | //! values. | |
145 | //! | |
146 | //! `make<map_tag>` requires all the keys to be unique and to have | |
147 | //! different hashes. If you need to create a map with duplicate keys | |
148 | //! or with keys whose hashes might collide, use `hana::to_map` or | |
149 | //! insert `(key, value)` pairs to an empty map successively. However, | |
150 | //! be aware that doing so will be much more compile-time intensive than | |
151 | //! using `make<map_tag>`, because the uniqueness of keys will have to be | |
152 | //! enforced. | |
153 | //! | |
154 | //! | |
155 | //! Example | |
156 | //! ------- | |
157 | //! @include example/map/make.cpp | |
158 | #ifdef BOOST_HANA_DOXYGEN_INVOKED | |
159 | template <> | |
160 | constexpr auto make<map_tag> = [](auto&& ...pairs) { | |
161 | return map<implementation_defined>{forwarded(pairs)...}; | |
162 | }; | |
163 | #endif | |
164 | ||
165 | //! Alias to `make<map_tag>`; provided for convenience. | |
166 | //! @relates hana::map | |
167 | //! | |
168 | //! | |
169 | //! Example | |
170 | //! ------- | |
171 | //! @include example/map/make.cpp | |
1e59de90 | 172 | BOOST_HANA_INLINE_VARIABLE constexpr auto make_map = make<map_tag>; |
7c673cae FG |
173 | |
174 | //! Equivalent to `to<map_tag>`; provided for convenience. | |
175 | //! @relates hana::map | |
1e59de90 | 176 | BOOST_HANA_INLINE_VARIABLE constexpr auto to_map = to<map_tag>; |
7c673cae FG |
177 | |
178 | //! Returns a `Sequence` of the keys of the map, in unspecified order. | |
179 | //! @relates hana::map | |
180 | //! | |
181 | //! | |
182 | //! Example | |
183 | //! ------- | |
184 | //! @include example/map/keys.cpp | |
185 | #ifdef BOOST_HANA_DOXYGEN_INVOKED | |
186 | constexpr auto keys = [](auto&& map) { | |
187 | return implementation_defined; | |
188 | }; | |
189 | #endif | |
190 | ||
191 | //! Returns a `Sequence` of the values of the map, in unspecified order. | |
192 | //! @relates hana::map | |
193 | //! | |
194 | //! | |
195 | //! Example | |
196 | //! ------- | |
197 | //! @include example/map/values.cpp | |
198 | #ifdef BOOST_HANA_DOXYGEN_INVOKED | |
199 | constexpr auto values = [](auto&& map) -> decltype(auto) { | |
200 | return implementation_defined; | |
201 | }; | |
202 | #else | |
203 | struct values_t { | |
204 | template <typename Map> | |
205 | constexpr decltype(auto) operator()(Map&& map) const; | |
206 | }; | |
207 | ||
1e59de90 | 208 | BOOST_HANA_INLINE_VARIABLE constexpr values_t values{}; |
7c673cae FG |
209 | #endif |
210 | ||
211 | //! Inserts a new key/value pair in a map. | |
212 | //! @relates hana::map | |
213 | //! | |
214 | //! Given a `(key, value)` pair, `insert` inserts this new pair into a | |
215 | //! map. If the map already contains this key, nothing is done and the | |
216 | //! map is returned as-is. | |
217 | //! | |
218 | //! | |
219 | //! @param map | |
220 | //! The map in which to insert a `(key,value)` pair. | |
221 | //! | |
222 | //! @param pair | |
223 | //! An arbitrary `Product` representing a `(key, value)` pair to insert | |
224 | //! in the map. The `key` must be compile-time `Comparable`. | |
225 | //! | |
226 | //! | |
227 | //! Example | |
228 | //! ------- | |
229 | //! @include example/map/insert.cpp | |
230 | #ifdef BOOST_HANA_DOXYGEN_INVOKED | |
231 | constexpr auto insert = [](auto&& map, auto&& pair) { | |
232 | return tag-dispatched; | |
233 | }; | |
234 | #endif | |
235 | ||
236 | //! Removes a key/value pair from a map. | |
237 | //! @relates hana::map | |
238 | //! | |
239 | //! Returns a new `hana::map` containing all the elements of the original, | |
240 | //! except for the `(key, value)` pair whose `key` compares `equal` | |
241 | //! to the given key. If the map does not contain such an element, | |
242 | //! a new map equal to the original is returned. | |
243 | //! | |
244 | //! | |
245 | //! @param map | |
246 | //! The map in which to erase a `key`. | |
247 | //! | |
248 | //! @param key | |
249 | //! A key to remove from the map. It must be compile-time `Comparable`. | |
250 | //! | |
251 | //! | |
252 | //! Example | |
253 | //! ------- | |
254 | //! @include example/map/erase_key.cpp | |
255 | #ifdef BOOST_HANA_DOXYGEN_INVOKED | |
256 | constexpr auto erase_key = [](auto&& map, auto&& key) { | |
257 | return tag-dispatched; | |
258 | }; | |
259 | #endif | |
b32b8144 FG |
260 | |
261 | //! Returns the union of two maps. | |
262 | //! @relates hana::map | |
263 | //! | |
264 | //! Given two maps `xs` and `ys`, `hana::union_(xs, ys)` is a new map | |
265 | //! containing all the elements of `xs` and all the elements of `ys`, | |
266 | //! without duplicates. If both `xs` and `ys` contain an element with the | |
267 | //! same `key`, the one in `ys` is taken. Functionally, | |
268 | //! `hana::union_(xs, ys)` is equivalent to | |
269 | //! @code | |
270 | //! hana::fold_left(xs, ys, hana::insert) | |
271 | //! @endcode | |
272 | //! | |
273 | //! @param xs, ys | |
274 | //! The two maps to compute the union of. | |
275 | //! | |
276 | //! | |
277 | //! Example | |
278 | //! ------- | |
279 | //! @include example/map/union.cpp | |
280 | #ifdef BOOST_HANA_DOXYGEN_INVOKED | |
281 | constexpr auto union_ = [](auto&& xs, auto&& ys) { | |
282 | return tag-dispatched; | |
283 | }; | |
284 | #endif | |
285 | ||
286 | //! Returns the intersection of two maps. | |
287 | //! @relates hana::map | |
288 | //! | |
289 | //! Given two maps `xs` and `ys`, `intersection(xs, ys)` is a new map | |
290 | //! containing exactly those (key, value) pairs from xs, for which key | |
291 | //! is present in `ys`. | |
292 | //! In other words, the following holds for any object `pair(k, v)`: | |
293 | //! @code | |
294 | //! pair(k, v) ^in^ intersection(xs, ys) if and only if (k, v) ^in^ xs && k ^in^ keys(ys) | |
295 | //! @endcode | |
296 | //! | |
297 | //! | |
298 | //! @note | |
299 | //! This function is not commutative, i.e. `intersection(xs, ys)` is not | |
300 | //! necessarily the same as `intersection(ys, xs)`. Indeed, the set of keys | |
301 | //! in `intersection(xs, ys)` is always the same as the set of keys in | |
302 | //! `intersection(ys, xs)`, but the value associated to each key may be | |
303 | //! different. `intersection(xs, ys)` contains values present in `xs`, and | |
304 | //! `intersection(ys, xs)` contains values present in `ys`. | |
305 | //! | |
306 | //! | |
307 | //! @param xs, ys | |
308 | //! Two maps to intersect. | |
309 | //! | |
310 | //! | |
311 | //! Example | |
312 | //! ------- | |
313 | //! @include example/map/intersection.cpp | |
314 | #ifdef BOOST_HANA_DOXYGEN_INVOKED | |
315 | constexpr auto intersection = [](auto&& xs, auto&& ys) { | |
316 | return tag-dispatched; | |
317 | }; | |
318 | #endif | |
319 | ||
320 | //! Returns the difference of two maps. | |
321 | //! @relates hana::map | |
322 | //! | |
323 | //! Given two maps `xs` and `ys`, `difference(xs, ys)` is a new map | |
324 | //! containing exactly those (key, value) pairs from xs, for which key | |
325 | //! is not present in `keys(ys)`. | |
326 | //! In other words, the following holds for any object `pair(k, v)`: | |
327 | //! @code | |
328 | //! pair(k, v) ^in^ difference(xs, ys) if and only if (k, v) ^in^ xs && k ^not in^ keys(ys) | |
329 | //! @endcode | |
330 | //! | |
331 | //! | |
332 | //! @note | |
333 | //! This function is not commutative, i.e. `difference(xs, ys)` is not | |
334 | //! necessarily the same as `difference(ys, xs)`. | |
335 | //! Indeed, consider the case where `xs` is empty and `ys` isn't. | |
336 | //! In that case, `difference(xs, ys)` is empty, but `difference(ys, xs)` | |
337 | //! is equal to `ys`. | |
338 | //! For symmetric version of this operation, see `symmetric_difference`. | |
339 | //! | |
340 | //! | |
341 | //! @param xs, ys | |
342 | //! Two maps to compute the difference of. | |
343 | //! | |
344 | //! | |
345 | //! Example | |
346 | //! ------- | |
347 | //! @include example/map/intersection.cpp | |
348 | #ifdef BOOST_HANA_DOXYGEN_INVOKED | |
349 | constexpr auto difference = [](auto&& xs, auto&& ys) { | |
350 | return tag-dispatched; | |
351 | }; | |
352 | #endif | |
353 | ||
354 | //! Returns the symmetric set-theoretic difference of two maps. | |
355 | //! @relates hana::map | |
356 | //! | |
357 | //! Given two sets `xs` and `ys`, `symmetric_difference(xs, ys)` is a new | |
358 | //! map containing all the elements of `xs` whose keys are not contained in `keys(ys)`, | |
359 | //! and all the elements of `ys` whose keys are not contained in `keys(xs)`. The | |
360 | //! symmetric difference of two maps satisfies the following: | |
361 | //! @code | |
362 | //! symmetric_difference(xs, ys) == union_(difference(xs, ys), difference(ys, xs)) | |
363 | //! @endcode | |
364 | //! | |
365 | //! | |
366 | //! @param xs, ys | |
367 | //! Two maps to compute the symmetric difference of. | |
368 | //! | |
369 | //! | |
370 | //! Example | |
371 | //! ------- | |
372 | //! @include example/map/symmetric_difference.cpp | |
373 | #ifdef BOOST_HANA_DOXYGEN_INVOKED | |
374 | constexpr auto symmetric_difference = [](auto&& xs, auto&& ys) { | |
375 | return tag-dispatched; | |
376 | }; | |
377 | #endif | |
378 | ||
379 | ||
1e59de90 | 380 | }} // end namespace boost::hana |
7c673cae FG |
381 | |
382 | #endif // !BOOST_HANA_FWD_MAP_HPP |