map.hpp 13 KB

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