/*************************************************************************** * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht * * Copyright (c) QuantStack * * * * Distributed under the terms of the BSD 3-Clause License. * * * * The full license is in the file LICENSE, distributed with this software. * ****************************************************************************/ #ifndef XTL_XITERATOR_BASE_HPP #define XTL_XITERATOR_BASE_HPP #include #include namespace xtl { /************************************** * class xbidirectional_iterator_base * **************************************/ template class xbidirectional_iterator_base { public: using derived_type = I; using value_type = T; using reference = R; using pointer = P; using difference_type = D; using iterator_category = std::bidirectional_iterator_tag; inline friend derived_type operator++(derived_type& d, int) { derived_type tmp(d); ++d; return tmp; } inline friend derived_type operator--(derived_type& d, int) { derived_type tmp(d); --d; return tmp; } inline friend bool operator!=(const derived_type& lhs, const derived_type& rhs) { return !(lhs == rhs); } }; template using xbidirectional_iterator_base2 = xbidirectional_iterator_base; template using xbidirectional_iterator_base3 = xbidirectional_iterator_base; /******************************** * xrandom_access_iterator_base * ********************************/ template class xrandom_access_iterator_base : public xbidirectional_iterator_base { public: using derived_type = I; using value_type = T; using reference = R; using pointer = P; using difference_type = D; using iterator_category = std::random_access_iterator_tag; inline reference operator[](difference_type n) const { return *(*static_cast(this) + n); } inline friend derived_type operator+(const derived_type& it, difference_type n) { derived_type tmp(it); return tmp += n; } inline friend derived_type operator+(difference_type n, const derived_type& it) { derived_type tmp(it); return tmp += n; } inline friend derived_type operator-(const derived_type& it, difference_type n) { derived_type tmp(it); return tmp -= n; } inline friend bool operator<=(const derived_type& lhs, const derived_type& rhs) { return !(rhs < lhs); } inline friend bool operator>=(const derived_type& lhs, const derived_type& rhs) { return !(lhs < rhs); } inline friend bool operator>(const derived_type& lhs, const derived_type& rhs) { return rhs < lhs; } }; template using xrandom_access_iterator_base2 = xrandom_access_iterator_base; template using xrandom_access_iterator_base3 = xrandom_access_iterator_base; /******************************* * xrandom_access_iterator_ext * *******************************/ // Extension for random access iterators defining operator[] and operator+ overloads // accepting size_t arguments. template class xrandom_access_iterator_ext { public: using derived_type = I; using reference = R; using size_type = std::size_t; inline reference operator[](size_type n) const { return *(*static_cast(this) + n); } inline friend derived_type operator+(const derived_type& it, size_type n) { derived_type tmp(it); return tmp += n; } inline friend derived_type operator+(size_type n, const derived_type& it) { derived_type tmp(it); return tmp += n; } inline friend derived_type operator-(const derived_type& it, size_type n) { derived_type tmp(it); return tmp -= n; } }; /***************** * xkey_iterator * *****************/ template class xkey_iterator : public xbidirectional_iterator_base, const typename M::key_type> { public: using self_type = xkey_iterator; using base_type = xbidirectional_iterator_base; using value_type = typename base_type::value_type; using reference = typename base_type::reference; using pointer = typename base_type::pointer; using difference_type = typename base_type::difference_type; using iterator_category = typename base_type::iterator_category; using subiterator = typename M::const_iterator; inline xkey_iterator(subiterator it) noexcept : m_it(it) { } inline self_type& operator++() { ++m_it; return *this; } inline self_type& operator--() { --m_it; return *this; } inline reference operator*() const { return m_it->first; } inline pointer operator->() const { return&(m_it->first); } inline bool operator==(const self_type& rhs) const { return m_it == rhs.m_it; } private: subiterator m_it; }; /******************* * xvalue_iterator * *******************/ namespace detail { template struct xvalue_iterator_types { using subiterator = typename M::iterator; using value_type = typename M::mapped_type; using reference = value_type&; using pointer = value_type*; using difference_type = typename subiterator::difference_type; }; template struct xvalue_iterator_types { using subiterator = typename M::const_iterator; using value_type = typename M::mapped_type; using reference = const value_type&; using pointer = const value_type*; using difference_type = typename subiterator::difference_type; }; } template class xvalue_iterator : xbidirectional_iterator_base3, detail::xvalue_iterator_types> { public: using self_type = xvalue_iterator; using base_type = xbidirectional_iterator_base3>; using value_type = typename base_type::value_type; using reference = typename base_type::reference; using pointer = typename base_type::pointer; using difference_type = typename base_type::difference_type; using subiterator = typename detail::xvalue_iterator_types::subiterator; inline xvalue_iterator(subiterator it) noexcept : m_it(it) { } inline self_type& operator++() { ++m_it; return *this; } inline self_type& operator--() { --m_it; return *this; } inline reference operator*() const { return m_it->second; } inline pointer operator->() const { return&(m_it->second); } inline bool operator==(const self_type& rhs) const { return m_it == rhs.m_it; } private: subiterator m_it; }; /********************** * xstepping_iterator * **********************/ template class xstepping_iterator : public xrandom_access_iterator_base3, std::iterator_traits> { public: using self_type = xstepping_iterator; using base_type = xrandom_access_iterator_base3>; using value_type = typename base_type::value_type; using reference = typename base_type::reference; using pointer = typename base_type::pointer; using difference_type = typename base_type::difference_type; using iterator_category = typename base_type::iterator_category; using subiterator = It; xstepping_iterator() = default; inline xstepping_iterator(subiterator it, difference_type step) noexcept : m_it(it), m_step(step) { } inline self_type& operator++() { std::advance(m_it, m_step); return *this; } inline self_type& operator--() { std::advance(m_it, -m_step); return *this; } inline self_type& operator+=(difference_type n) { std::advance(m_it, n*m_step); return *this; } inline self_type& operator-=(difference_type n) { std::advance(m_it, -n*m_step); return *this; } inline difference_type operator-(const self_type& rhs) const { return std::distance(rhs.m_it, m_it) / m_step; } inline reference operator*() const { return *m_it; } inline pointer operator->() const { return m_it; } inline bool equal(const self_type& rhs) const { return m_it == rhs.m_it && m_step == rhs.m_step; } inline bool less_than(const self_type& rhs) const { return m_it < rhs.m_it && m_step == rhs.m_step; } private: subiterator m_it; difference_type m_step; }; template inline bool operator==(const xstepping_iterator& lhs, const xstepping_iterator& rhs) { return lhs.equal(rhs); } template inline bool operator<(const xstepping_iterator& lhs, const xstepping_iterator& rhs) { return lhs.less_than(rhs); } template inline xstepping_iterator make_stepping_iterator(It it, typename std::iterator_traits::difference_type step) { return xstepping_iterator(it, step); } /*********************** * common_iterator_tag * ***********************/ template struct common_iterator_tag : std::common_type::iterator_category...> { }; template using common_iterator_tag_t = typename common_iterator_tag::type; } #endif