diff --git a/src/rttr/detail/impl/associative_mapper_impl.h b/src/rttr/detail/impl/associative_mapper_impl.h index 99cc8814..13d5aca1 100644 --- a/src/rttr/detail/impl/associative_mapper_impl.h +++ b/src/rttr/detail/impl/associative_mapper_impl.h @@ -72,6 +72,14 @@ struct associative_container_mapper_wrapper : iterator_wrapper_base return variant(std::ref(base_class::get_key(it))); } + template::value, int> = 0> + static variant + get_value(iterator_data& itr) + { + auto& it = itr_wrapper::get_iterator(itr); + return variant(std::ref(base_class::get_value(it))); + } + template::value, int> = 0> static variant get_value(const iterator_data& itr) @@ -80,6 +88,13 @@ struct associative_container_mapper_wrapper : iterator_wrapper_base return variant(std::ref(base_class::get_value(it))); } + template::value, int> = 0> + static variant + get_value(iterator_data& itr) + { + return variant(); + } + template::value, int> = 0> static variant get_value(const iterator_data& itr) @@ -478,6 +493,11 @@ struct associative_container_empty return variant(); } + static variant get_value(iterator_data& itr) + { + return variant(); + } + static variant get_value(const iterator_data& itr) { return variant(); diff --git a/src/rttr/detail/variant_associative_view/variant_associative_view_private.h b/src/rttr/detail/variant_associative_view/variant_associative_view_private.h index eea43fcb..74e4807f 100644 --- a/src/rttr/detail/variant_associative_view/variant_associative_view_private.h +++ b/src/rttr/detail/variant_associative_view/variant_associative_view_private.h @@ -58,6 +58,7 @@ class RTTR_LOCAL variant_associative_view_private m_delete_func(associative_container_empty::destroy), m_get_key_func(associative_container_empty::get_key), m_get_value_func(associative_container_empty::get_value), + m_get_const_value_func(associative_container_empty::get_value), m_advance_func(associative_container_empty::advance), m_find_func(associative_container_empty::find), m_erase_func(associative_container_empty::erase), @@ -85,6 +86,7 @@ class RTTR_LOCAL variant_associative_view_private m_delete_func(associative_container_mapper_wrapper::destroy), m_get_key_func(associative_container_mapper_wrapper::get_key), m_get_value_func(associative_container_mapper_wrapper::get_value), + m_get_const_value_func(associative_container_mapper_wrapper::get_value), m_advance_func(associative_container_mapper_wrapper::advance), m_find_func(associative_container_mapper_wrapper::find), m_erase_func(associative_container_mapper_wrapper::erase), @@ -157,22 +159,37 @@ class RTTR_LOCAL variant_associative_view_private return m_get_key_func(itr); } - RTTR_INLINE const variant get_value(const iterator_data& itr) const + RTTR_INLINE variant get_value(iterator_data& itr) const { return m_get_value_func(itr); } - RTTR_INLINE const std::pair get_key_value(const iterator_data& itr) const + RTTR_INLINE const variant get_value(const iterator_data& itr) const + { + return m_get_const_value_func(itr); + } + + RTTR_INLINE std::pair get_key_value(iterator_data& itr) const { return {m_get_key_func(itr), m_get_value_func(itr)}; } + RTTR_INLINE const std::pair get_key_value(const iterator_data& itr) const + { + return {m_get_key_func(itr), m_get_const_value_func(itr)}; + } + RTTR_INLINE void advance(iterator_data& itr, std::ptrdiff_t index) const { m_advance_func(itr, index); } + RTTR_INLINE void find(iterator_data& itr, argument& key) const + { + m_find_func(m_container, itr, key); + } + RTTR_INLINE void find(iterator_data& itr, argument& key) { m_find_func(m_container, itr, key); @@ -216,7 +233,8 @@ class RTTR_LOCAL variant_associative_view_private using create_func = void(*)(iterator_data& itr_tgt, const iterator_data& itr_src); using delete_func = void(*)(iterator_data& itr); using get_key_func = variant (*)(const iterator_data& itr); - using get_value_func = variant (*)(const iterator_data& itr); + using get_value_func = variant(*)(iterator_data& itr); + using get_const_value_func = variant(*)(const iterator_data& itr); using clear_func = void(*)(void* container); using erase_func = std::size_t(*)(void* container, argument& key); using find_func = void(*)(void* container, detail::iterator_data& itr, argument& key); @@ -238,6 +256,7 @@ class RTTR_LOCAL variant_associative_view_private delete_func m_delete_func; get_key_func m_get_key_func; get_value_func m_get_value_func; + get_const_value_func m_get_const_value_func; advance_func m_advance_func; find_func m_find_func; erase_func m_erase_func; diff --git a/src/rttr/variant_associative_view.cpp b/src/rttr/variant_associative_view.cpp index ee2119cc..3ccd4ce9 100644 --- a/src/rttr/variant_associative_view.cpp +++ b/src/rttr/variant_associative_view.cpp @@ -151,7 +151,19 @@ std::pair variant_associative_vi ///////////////////////////////////////////////////////////////////////////////////////// -variant_associative_view::const_iterator variant_associative_view::find(argument arg) +variant_associative_view::iterator variant_associative_view::find(argument arg) +{ + iterator itr(&m_view); + + m_view.find(itr.m_itr, arg); + + return itr; +} + + +///////////////////////////////////////////////////////////////////////////////////////// + +variant_associative_view::const_iterator variant_associative_view::find(argument arg) const { const_iterator itr(&m_view); @@ -190,6 +202,17 @@ variant_associative_view::equal_range(argument key) ///////////////////////////////////////////////////////////////////////////////////////// +variant_associative_view::iterator variant_associative_view::begin() +{ + iterator itr(&m_view); + + m_view.begin(itr.m_itr); + + return itr; +} + +///////////////////////////////////////////////////////////////////////////////////////// + variant_associative_view::const_iterator variant_associative_view::begin() const { const_iterator itr(&m_view); @@ -201,6 +224,17 @@ variant_associative_view::const_iterator variant_associative_view::begin() const ///////////////////////////////////////////////////////////////////////////////////////// +variant_associative_view::iterator variant_associative_view::end() +{ + iterator itr(&m_view); + + m_view.end(itr.m_itr); + + return itr; +} + +///////////////////////////////////////////////////////////////////////////////////////// + variant_associative_view::const_iterator variant_associative_view::end() const { const_iterator itr(&m_view); @@ -214,6 +248,162 @@ variant_associative_view::const_iterator variant_associative_view::end() const ///////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////// +variant_associative_view::iterator::iterator(detail::variant_associative_view_private* view) RTTR_NOEXCEPT +: m_view(view) +{ +} + +///////////////////////////////////////////////////////////////////////////////////////// + +variant_associative_view::iterator::~iterator() +{ + m_view->destroy(m_itr); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +variant_associative_view::iterator::iterator(const iterator &other) +: m_view(other.m_view), + m_itr(other.m_itr) +{ + m_view->copy(m_itr, other.m_itr); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +variant_associative_view::iterator& variant_associative_view::iterator::operator=(iterator other) +{ + swap(other); + return *this; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +void variant_associative_view::iterator::swap(iterator& other) +{ + std::swap(m_itr, other.m_itr); + std::swap(m_view, other.m_view); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +std::pair variant_associative_view::iterator::operator*() +{ + return m_view->get_key_value(m_itr); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +const variant variant_associative_view::iterator::get_key() const +{ + return m_view->get_key(m_itr); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +variant variant_associative_view::iterator::get_value() +{ + return m_view->get_value(m_itr); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +variant_associative_view::iterator& variant_associative_view::iterator::operator++() +{ + m_view->advance(m_itr, 1); + return *this; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +variant_associative_view::iterator variant_associative_view::iterator::operator++(int) +{ + iterator result(m_view); + + m_view->copy(result.m_itr, m_itr); + m_view->advance(m_itr, 1); + + return result; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +variant_associative_view::iterator& variant_associative_view::iterator::operator--() +{ + m_view->advance(m_itr, -1); + return *this; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +variant_associative_view::iterator variant_associative_view::iterator::operator--(int) +{ + iterator result(m_view); + + m_view->copy(result.m_itr, m_itr); + m_view->advance(m_itr, -1); + + return result; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +variant_associative_view::iterator& variant_associative_view::iterator::operator+=(int i) +{ + m_view->advance(m_itr, i); + return *this; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +variant_associative_view::iterator& variant_associative_view::iterator::operator-=(int i) +{ + m_view->advance(m_itr, -i); + return *this; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +variant_associative_view::iterator variant_associative_view::iterator::operator+(int i) const +{ + iterator result(m_view); + + m_view->copy(result.m_itr, m_itr); + result.m_view->advance(result.m_itr, i); + + return result; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +variant_associative_view::iterator variant_associative_view::iterator::operator-(int i) const +{ + iterator result(m_view); + + m_view->copy(result.m_itr, m_itr); + result.m_view->advance(result.m_itr, -i); + + return result; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +bool variant_associative_view::iterator::operator==(const iterator& other) const +{ + return m_view->equal(m_itr, other.m_itr); +} + +///////////////////////////////////////////////////////////////////////////////////////// + +bool variant_associative_view::iterator::operator!=(const iterator& other) const +{ + return !m_view->equal(m_itr, other.m_itr); +} + +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////// + variant_associative_view::const_iterator::const_iterator(const detail::variant_associative_view_private* view) RTTR_NOEXCEPT : m_view(view) { diff --git a/src/rttr/variant_associative_view.h b/src/rttr/variant_associative_view.h index 44029ee3..a777108e 100644 --- a/src/rttr/variant_associative_view.h +++ b/src/rttr/variant_associative_view.h @@ -92,6 +92,7 @@ namespace rttr class RTTR_API variant_associative_view { public: + class iterator; class const_iterator; /*! @@ -217,7 +218,14 @@ class RTTR_API variant_associative_view * * \return The element with key equivalent to \p key. If no element is found an invalid iterator is returned. */ - const_iterator find(argument key); + iterator find(argument key); + + /*! + * \brief Finds an element with specific key \p key . + * + * \return The element with key equivalent to \p key. If no element is found an invalid iterator is returned. + */ + const_iterator find(argument key) const; /*! * \brief Removes the element (if one exists) with the key equivalent to \p key. @@ -276,6 +284,15 @@ class RTTR_API variant_associative_view * * \return Iterator to the first element . */ + iterator begin(); + + /*! + * \brief Returns a const_iterator to the first element of the container. + * + * \see end() + * + * \return Iterator to the first element . + */ const_iterator begin() const; /*! @@ -285,8 +302,144 @@ class RTTR_API variant_associative_view * * \return Iterator to the element following the last element. */ + iterator end(); + + /*! + * \brief Returns a const_iterator to the element following the last element of the container. + * + * \see begin() + * + * \return Iterator to the element following the last element. + */ const_iterator end() const; + /*! + * The \ref variant_associative_view::iterator allows iteration over an associative container in a variant. + * An instance can only be created by a non-const variant_associative_view. + * + * \see variant_associative_view::const_iterator + */ + class RTTR_API iterator + { + public: + using self_type = iterator; + using value_type = variant; + + /*! + * \brief Destroys the variant_associative_view::iterator + */ + ~iterator(); + + /*! + * \brief Creates a copy of \p other + */ + iterator(const iterator& other); + + /*! + * \brief Assigns \p other to `this`. + */ + iterator& operator=(iterator other); + + /*! + * Returns the underlying key and value stored in a `std::pair`. + * The actual data in the variant is stored inside a `std::reference_wrapper` + * + * \see variant::extract_wrapped_value(), variant::get_wrapped_value() + */ + std::pair operator*(); + + /*! + * \brief Returns the current key, stored inside a `std::reference_wrapper` + * and copied to a variant. + * + * \see variant::extract_wrapped_value(), variant::get_wrapped_value() + */ + const variant get_key() const; + + /*! + * \brief Returns the current value, stored inside a `std::reference_wrapper` + * and copied to a variant. + * + * \see variant::extract_wrapped_value(), variant::get_wrapped_value() + */ + variant get_value(); + + /*! + * \brief Pre-increment operator advances the iterator to the next item + * in the container and returns an iterator to the new current item. + * + * \remark Calling this function on and iterator with value variant_associative_view::end() + * leads to undefined behaviour. + */ + iterator &operator++(); + + /*! + * \brief Post-increment operator advances the iterator to the next item + * in the container and returns an iterator to the previously current item. + */ + iterator operator++(int); + + /*! + * \brief Pre-decrement operator makes the preceding item current and returns + * an iterator to the new current item. + * + * \remark Calling this function on and iterator with value variant_associative_view::begin() + * leads to undefined behaviour. + */ + iterator &operator--(); + + /*! + * \brief Post-decrement operator makes the preceding item current + * and returns an iterator to the previously current item. + */ + iterator operator--(int); + + /*! + * \brief Advances the iterator by i items. + */ + iterator &operator+=(int i); + + /*! + * \brief Returns an iterator to the item at i positions backward from this iterator. + */ + iterator &operator-=(int i); + + /*! + * \brief Returns an iterator to the item at i positions forward from this iterator. + */ + iterator operator+(int i) const; + + /*! + * \brief Returns an iterator to the item at i positions backward from this iterator. + */ + iterator operator-(int i) const; + + /*! + * \brief Returns `true` if \p other points to the same item + * as this iterator; otherwise returns false. + * + * \see \ref iterator::operator!= "operator!=" + */ + bool operator==(const iterator& other) const; + + /*! + * \brief Returns true if \p other points to a different item + * than this iterator; otherwise returns false. + * + * \see \ref operator== "operator==" + */ + bool operator!=(const iterator& other) const; + + private: + iterator(detail::variant_associative_view_private* view) RTTR_NOEXCEPT; + void swap(iterator& other); + + friend class variant_associative_view; + + detail::variant_associative_view_private* m_view; + detail::iterator_data m_itr; + }; + /*! * The \ref variant_associative_view::const_iterator allows iteration over an associative container in a variant. * An instance can only be created by an variant_associative_view.