variant_associative_view.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. /************************************************************************************
  2. * *
  3. * Copyright (c) 2014 - 2018 Axel Menzel <info@rttr.org> *
  4. * *
  5. * This file is part of RTTR (Run Time Type Reflection) *
  6. * License: MIT License *
  7. * *
  8. * Permission is hereby granted, free of charge, to any person obtaining *
  9. * a copy of this software and associated documentation files (the "Software"), *
  10. * to deal in the Software without restriction, including without limitation *
  11. * the rights to use, copy, modify, merge, publish, distribute, sublicense, *
  12. * and/or sell copies of the Software, and to permit persons to whom the *
  13. * Software is furnished to do so, subject to the following conditions: *
  14. * *
  15. * The above copyright notice and this permission notice shall be included in *
  16. * all copies or substantial portions of the Software. *
  17. * *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
  24. * SOFTWARE. *
  25. * *
  26. *************************************************************************************/
  27. #ifndef RTTR_VARIANT_ASSOCIATIVE_VIEW_H_
  28. #define RTTR_VARIANT_ASSOCIATIVE_VIEW_H_
  29. #include "rttr/detail/base/core_prerequisites.h"
  30. #include "rttr/detail/misc/misc_type_traits.h"
  31. #include "rttr/variant.h"
  32. #include "rttr/detail/variant_associative_view/variant_associative_view_private.h"
  33. #include <cstddef>
  34. #include <vector>
  35. #include <memory>
  36. namespace rttr
  37. {
  38. class type;
  39. class instance;
  40. class argument;
  41. /*!
  42. * The \ref variant_associative_view describes a class that refers to an
  43. * <a target="_blank" href=https://en.wikipedia.org/wiki/Associative_containers>associative container</a> (e.g: `std::map`)
  44. * inside a \ref variant.
  45. * With an instance of that class you can set/get values of such container,
  46. * without having access to the type declaration of the type or it's elements.
  47. *
  48. * A \ref variant_associative_view can be created directly from a \ref variant with its member function \ref variant::create_associative_view() "create_associative_view()".
  49. * \remark The instance of an variant_associative_view is always valid as long as the referenced \ref variant is valid, otherwise accessing a variant_associative_view
  50. * is undefined behaviour.
  51. *
  52. * Meta Information
  53. * ----------------
  54. *
  55. * RTTR recognize whether a type is an associative container or not with the help of the \ref associative_container_mapper class template.
  56. * This call can access different container types via one common interface.
  57. * At the moment there exist specializations for following types:
  58. * `std::set<Key>`, `std::map<Key, T>`, `std::multiset<Key>`, `std::multimap<Key, T>`, `std::unordered_set<Key>`,
  59. * `std::unordered_map<Key, T>`, `std::unordered_multiset<Key>` and `std::unordered_multimap<Key, T>`.
  60. *
  61. * Copying and Assignment
  62. * ----------------------
  63. * A \ref variant_associative_view object can be copied and assigned,
  64. * however each copy will reference the data of same underlying \ref variant value.
  65. *
  66. * Typical Usage
  67. * ----------------------
  68. *
  69. * \code{.cpp}
  70. * std::map<int, std::string> my_map = { { 1, "one" }, { 2, "two" }, { 3, "three" } };
  71. * variant var = my_map;
  72. * if (var.is_associative_container())
  73. * {
  74. * variant_associative_view view = var.create_associative_view();
  75. * std::cout << view.get_size() << std::endl; // prints: '3'
  76. * for (const auto& item : view)
  77. * {
  78. * // remark that the key and value are stored inside a 'std::reference_wrapper'
  79. * std::cout << "Key: " << item.first.extract_wrapped_value().to_string() << " ";
  80. * std::cout << "Value: " << item.second.extract_wrapped_value().to_string() << std::endl;
  81. * }
  82. * }
  83. * \endcode
  84. *
  85. * \see variant
  86. */
  87. class RTTR_API variant_associative_view
  88. {
  89. public:
  90. class const_iterator;
  91. /*!
  92. * \brief Constructs an invalid variant_associative_view object.
  93. *
  94. * \see is_valid()
  95. */
  96. variant_associative_view();
  97. /*!
  98. * \brief Constructs a copy of the given variant_associative_view \p other.
  99. */
  100. variant_associative_view(const variant_associative_view& other);
  101. /*!
  102. * \brief Destroys the variant_associative_view.
  103. *
  104. * \remark The underlying data is not destroyed.
  105. */
  106. ~variant_associative_view() RTTR_NOEXCEPT;
  107. /*!
  108. * \brief Assigns the value of the \a other variant_associative_view to this variant_associative_view.
  109. *
  110. * \return A reference to the variant_associative_view with the new data.
  111. */
  112. variant_associative_view& operator=(const variant_associative_view& other) RTTR_NOEXCEPT;
  113. /*!
  114. * \brief Returns true if this variant_associative_view is valid, that means the object is holding some data.
  115. * When the variant_associative_view doesn't hold any data it will return false.
  116. *
  117. * \return True if this \ref variant_associative_view is valid, otherwise false.
  118. */
  119. bool is_valid() const RTTR_NOEXCEPT;
  120. /*!
  121. * \brief Convenience function to check if this \ref variant_associative_view is valid or not.
  122. *
  123. * \see is_valid()
  124. *
  125. * \return True if this \ref variant_associative_view is valid, otherwise false.
  126. */
  127. explicit operator bool() const RTTR_NOEXCEPT;
  128. /*!
  129. * \brief Swaps this variant_associative_view with the \a other variant_associative_view.
  130. */
  131. void swap(variant_associative_view& other) RTTR_NOEXCEPT;
  132. /*!
  133. * \brief Returns the \ref type object of this associative container.
  134. *
  135. * \remark When the view is not valid, this function will return an invalid type object.
  136. *
  137. * \return \ref type "Type" of the associative container.
  138. */
  139. type get_type() const RTTR_NOEXCEPT;
  140. /*!
  141. * \brief Returns the \ref type from the key of this associative container.
  142. *
  143. * \remark When the view is not valid, this function will return an invalid type object.
  144. *
  145. * \return \ref type "Type" from the key of the associative container.
  146. */
  147. type get_key_type() const RTTR_NOEXCEPT;
  148. /*!
  149. * \brief Returns the \ref type object from the value of this associative container.
  150. *
  151. * \remark When the view is not valid, this function will return an invalid type object.
  152. *
  153. * \return \ref type "Type" from the value of the associative container.
  154. */
  155. type get_value_type() const RTTR_NOEXCEPT;
  156. /*!
  157. * \brief Returns `true`, when this associative container stores only keys.
  158. * When also value are stored, it will return `false`.
  159. *
  160. * For example an `std::set` has no values, it's a key-only associative container. Then this method returns `true`.
  161. * An `std::map<K,V>` on the other hand contains keys and values. So this method will then return `false`.
  162. * A simple convenience method instead of calling: `get_value_type().is_valid() == false;`
  163. *
  164. * \return `true`, when this associative container stores only keys; otherwise `false`.
  165. */
  166. bool is_key_only_type() const RTTR_NOEXCEPT;
  167. /*!
  168. * \brief Checks if the container has no elements.
  169. *
  170. * \return `true` if container is empty, otherwise `false`.
  171. */
  172. bool is_empty() const RTTR_NOEXCEPT;
  173. /*!
  174. * \brief Returns the number of elements in the associative container.
  175. *
  176. * \return The number of elements in the associative container.
  177. */
  178. std::size_t get_size() const RTTR_NOEXCEPT;
  179. /*!
  180. * \brief Insert a key into the container.
  181. *
  182. * \return A pair consisting of an iterator to the inserted element (or to the element that prevented the insertion)
  183. * and a bool denoting whether the insertion took place.
  184. */
  185. std::pair<const_iterator, bool> insert(argument key);
  186. /*!
  187. * \brief Insert a key-value pair into the container.
  188. *
  189. * \return A pair consisting of an iterator to the inserted element (or to the element that prevented the insertion)
  190. * and a bool denoting whether the insertion took place.
  191. */
  192. std::pair<const_iterator, bool> insert(argument key, argument value);
  193. /*!
  194. * \brief Finds an element with specific key \p key .
  195. *
  196. * \return The element with key equivalent to \p key. If no element is found an invalid iterator is returned.
  197. */
  198. const_iterator find(argument key);
  199. /*!
  200. * \brief Removes the element (if one exists) with the key equivalent to \p key.
  201. *
  202. * \return The number of elements removed.
  203. */
  204. std::size_t erase(argument key);
  205. /*!
  206. * \brief Removes all elements from the container.
  207. *
  208. * \remark Invalidates all references, pointers, or iterators referring to contained elements.
  209. */
  210. void clear();
  211. /*!
  212. * \brief Returns a range containing all elements with the given \p key in the container.
  213. *
  214. * Example code:
  215. * \code{.cpp}
  216. * auto multimap = std::multimap<int, std::string>{ { 1, "A" }, { 2, "B" }, { 2, "C"}, { 2, "D" },
  217. * { 3, "E" }, { 3, "F" } };
  218. *
  219. * variant var = multimap;
  220. *
  221. * auto view = var.create_associative_view();
  222. * for (int i = 1; i <= 3; ++i)
  223. * {
  224. * std::cout << i << " =>";
  225. * auto range = view.equal_range(i);
  226. * for (auto itr = range.first; itr != range.second; ++itr)
  227. * {
  228. * std::cout << " " << itr.value().extract_wrapped_value().to_string();
  229. * }
  230. * std::cout << std::endl;
  231. * }
  232. *\endcode
  233. *
  234. * Output:
  235. * \code
  236. * 1 => A
  237. * 2 => B C D
  238. * 3 => E, F
  239. * \endcode
  240. *
  241. * \return std::pair containing a pair of iterators defining the wanted range:
  242. * the first pointing to the first element that is not less than \p key and
  243. * the second pointing to the first element greater than \p key.
  244. */
  245. std::pair<const_iterator, const_iterator> equal_range(argument key);
  246. /*!
  247. * \brief Returns an iterator to the first element of the container.
  248. *
  249. * \see end()
  250. *
  251. * \return Iterator to the first element .
  252. */
  253. const_iterator begin() const;
  254. /*!
  255. * \brief Returns an iterator to the element following the last element of the container.
  256. *
  257. * \see begin()
  258. *
  259. * \return Iterator to the element following the last element.
  260. */
  261. const_iterator end() const;
  262. /*!
  263. * The \ref variant_associative_view::const_iterator allows iteration over an associative container in a variant.
  264. * An instance can only be created by an variant_associative_view.
  265. *
  266. * Typical Usage
  267. * ----------------------
  268. *
  269. * \code{.cpp}
  270. * std::map<int, std::string> my_map = { { 1, "one" }, { 2, "two" }, { 3, "three" } };
  271. * variant var = my_map;
  272. * if (var.is_associative_container())
  273. * {
  274. * variant_associative_view view = var.create_associative_view();
  275. * std::cout << view.get_size() << std::endl; // prints: '3'
  276. * for (const auto& item : view)
  277. * {
  278. * // remark that the key and value are stored inside a 'std::reference_wrapper'
  279. * std::cout << "Key: " << item.first.extract_wrapped_value().to_string() << " ";
  280. * std::cout << "Value: " << item.second.extract_wrapped_value().to_string() << std::endl;
  281. * }
  282. * }
  283. * \endcode
  284. *
  285. * \remark The iterator is valid as long as the variant_associative_view and it corresponding variant is valid and not modified.
  286. */
  287. class RTTR_API const_iterator
  288. {
  289. public:
  290. using self_type = const_iterator;
  291. using value_type = variant;
  292. /*!
  293. * \brief Destroys the variant_associative_view::const_iterator
  294. */
  295. ~const_iterator();
  296. /*!
  297. * \brief Creates a copy of \p other
  298. */
  299. const_iterator(const const_iterator& other);
  300. /*!
  301. * \brief Assigns \p other to `this`.
  302. */
  303. const_iterator& operator=(const_iterator other);
  304. /*!
  305. * Returns the underlying key and value stored in a `std::pair<key, value>`.
  306. * The actual data in the variant is stored inside a `std::reference_wrapper<T>`
  307. *
  308. * \see variant::extract_wrapped_value(), variant::get_wrapped_value<T>()
  309. */
  310. const std::pair<variant, variant> operator*() const;
  311. /*!
  312. * \brief Returns the current key, stored inside a `std::reference_wrapper<T>`
  313. * and copied to a variant.
  314. *
  315. * \see variant::extract_wrapped_value(), variant::get_wrapped_value<T>()
  316. */
  317. const variant get_key() const;
  318. /*!
  319. * \brief Returns the current value, stored inside a `std::reference_wrapper<T>`
  320. * and copied to a variant.
  321. *
  322. * \see variant::extract_wrapped_value(), variant::get_wrapped_value<T>()
  323. */
  324. const variant get_value() const;
  325. /*!
  326. * \brief Pre-increment operator advances the iterator to the next item
  327. * in the container and returns an iterator to the new current item.
  328. *
  329. * \remark Calling this function on and iterator with value variant_associative_view::end()
  330. * leads to undefined behaviour.
  331. */
  332. const_iterator &operator++();
  333. /*!
  334. * \brief Post-increment operator advances the iterator to the next item
  335. * in the container and returns an iterator to the previously current item.
  336. */
  337. const_iterator operator++(int);
  338. /*!
  339. * \brief Pre-decrement operator makes the preceding item current and returns
  340. * an iterator to the new current item.
  341. *
  342. * \remark Calling this function on and iterator with value variant_associative_view::begin()
  343. * leads to undefined behaviour.
  344. */
  345. const_iterator &operator--();
  346. /*!
  347. * \brief Post-decrement operator makes the preceding item current
  348. * and returns an iterator to the previously current item.
  349. */
  350. const_iterator operator--(int);
  351. /*!
  352. * \brief Advances the iterator by i items.
  353. */
  354. const_iterator &operator+=(int i);
  355. /*!
  356. * \brief Returns an iterator to the item at i positions backward from this iterator.
  357. */
  358. const_iterator &operator-=(int i);
  359. /*!
  360. * \brief Returns an iterator to the item at i positions forward from this iterator.
  361. */
  362. const_iterator operator+(int i) const;
  363. /*!
  364. * \brief Returns an iterator to the item at i positions backward from this iterator.
  365. */
  366. const_iterator operator-(int i) const;
  367. /*!
  368. * \brief Returns `true` if \p other points to the same item
  369. * as this iterator; otherwise returns false.
  370. *
  371. * \see \ref const_iterator::operator!= "operator!="
  372. */
  373. bool operator==(const const_iterator& other) const;
  374. /*!
  375. * \brief Returns true if \p other points to a different item
  376. * than this iterator; otherwise returns false.
  377. *
  378. * \see \ref operator== "operator=="
  379. */
  380. bool operator!=(const const_iterator& other) const;
  381. private:
  382. const_iterator(const detail::variant_associative_view_private* view) RTTR_NOEXCEPT;
  383. void swap(const_iterator& other);
  384. friend class variant_associative_view;
  385. const detail::variant_associative_view_private* m_view;
  386. detail::iterator_data m_itr;
  387. };
  388. private:
  389. friend class variant;
  390. friend class argument;
  391. detail::variant_associative_view_private m_view;
  392. };
  393. } // end namespace rttr
  394. #endif // RTTR_VARIANT_ASSOCIATIVE_VIEW_H_