123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- /* Copyright 2016-2021 Joaquin M Lopez Munoz.
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- * See http://www.boost.org/libs/poly_collection for library home page.
- */
- #ifndef BOOST_POLY_COLLECTION_DETAIL_ITERATOR_IMPL_HPP
- #define BOOST_POLY_COLLECTION_DETAIL_ITERATOR_IMPL_HPP
- #if defined(_MSC_VER)
- #pragma once
- #endif
- #include <boost/detail/workaround.hpp>
- #include <boost/iterator/iterator_adaptor.hpp>
- #include <boost/iterator/iterator_facade.hpp>
- #include <boost/poly_collection/detail/is_constructible.hpp>
- #include <boost/poly_collection/detail/iterator_traits.hpp>
- #include <type_traits>
- #include <typeinfo>
- namespace boost{
- namespace poly_collection{
- namespace detail{
- /* Implementations of poly_collection::[const_][local_[base_]]iterator moved
- * out of class to allow for use in deduced contexts.
- */
- template<typename PolyCollection,bool Const>
- using iterator_impl_value_type=typename std::conditional<
- Const,
- const typename PolyCollection::value_type,
- typename PolyCollection::value_type
- >::type;
- template<typename PolyCollection,bool Const>
- class iterator_impl:
- public boost::iterator_facade<
- iterator_impl<PolyCollection,Const>,
- iterator_impl_value_type<PolyCollection,Const>,
- boost::forward_traversal_tag
- >
- {
- using segment_type=typename PolyCollection::segment_type;
- using const_segment_base_iterator=
- typename PolyCollection::const_segment_base_iterator;
- using const_segment_base_sentinel=
- typename PolyCollection::const_segment_base_sentinel;
- using const_segment_map_iterator=
- typename PolyCollection::const_segment_map_iterator;
- public:
- using value_type=iterator_impl_value_type<PolyCollection,Const>;
- private:
- iterator_impl(
- const_segment_map_iterator mapit,
- const_segment_map_iterator mapend)noexcept:
- mapit{mapit},mapend{mapend}
- {
- next_segment_position();
- }
- iterator_impl(
- const_segment_map_iterator mapit_,const_segment_map_iterator mapend_,
- const_segment_base_iterator segpos_)noexcept:
- mapit{mapit_},mapend{mapend_},segpos{segpos_}
- {
- if(mapit!=mapend&&segpos==sentinel()){
- ++mapit;
- next_segment_position();
- }
- }
- public:
- iterator_impl()=default;
- iterator_impl(const iterator_impl&)=default;
- iterator_impl& operator=(const iterator_impl&)=default;
- template<bool Const2,typename std::enable_if<!Const2>::type* =nullptr>
- iterator_impl(const iterator_impl<PolyCollection,Const2>& x):
- mapit{x.mapit},mapend{x.mapend},segpos{x.segpos}{}
-
- private:
- template<typename,bool>
- friend class iterator_impl;
- friend PolyCollection;
- friend class boost::iterator_core_access;
- template<typename>
- friend struct iterator_traits;
- value_type& dereference()const noexcept
- {return const_cast<value_type&>(*segpos);}
- bool equal(const iterator_impl& x)const noexcept{return segpos==x.segpos;}
- void increment()noexcept
- {
- if(++segpos==sentinel()){
- ++mapit;
- next_segment_position();
- }
- }
- void next_segment_position()noexcept
- {
- for(;mapit!=mapend;++mapit){
- segpos=segment().begin();
- if(segpos!=sentinel())return;
- }
- segpos=nullptr;
- }
- segment_type& segment()noexcept
- {return const_cast<segment_type&>(mapit->second);}
- const segment_type& segment()const noexcept{return mapit->second;}
- const_segment_base_sentinel sentinel()const noexcept
- {return segment().sentinel();}
- const_segment_map_iterator mapit,mapend;
- const_segment_base_iterator segpos;
- };
- template<typename PolyCollection,bool Const>
- struct poly_collection_of<iterator_impl<PolyCollection,Const>>
- {
- using type=PolyCollection;
- };
- template<typename PolyCollection,typename BaseIterator>
- class local_iterator_impl:
- public boost::iterator_adaptor<
- local_iterator_impl<PolyCollection,BaseIterator>,
- BaseIterator
- >
- {
- using segment_type=typename PolyCollection::segment_type;
- using segment_base_iterator=typename PolyCollection::segment_base_iterator;
- using const_segment_map_iterator=
- typename PolyCollection::const_segment_map_iterator;
- #if BOOST_WORKAROUND(BOOST_GCC_VERSION,>=90300)&&\
- BOOST_WORKAROUND(BOOST_GCC_VERSION,<100300)
- /* https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95888 */
- public:
- #else
- private:
- #endif
- template<typename Iterator>
- local_iterator_impl(
- const_segment_map_iterator mapit,
- Iterator it):
- local_iterator_impl::iterator_adaptor_{BaseIterator(it)},
- mapit{mapit}
- {}
- public:
- using base_iterator=BaseIterator;
- local_iterator_impl()=default;
- local_iterator_impl(const local_iterator_impl&)=default;
- local_iterator_impl& operator=(const local_iterator_impl&)=default;
- template<
- typename BaseIterator2,
- typename std::enable_if<
- std::is_convertible<BaseIterator2,BaseIterator>::value
- >::type* =nullptr
- >
- local_iterator_impl(
- const local_iterator_impl<PolyCollection,BaseIterator2>& x):
- local_iterator_impl::iterator_adaptor_{x.base()},
- mapit{x.mapit}{}
- template<
- typename BaseIterator2,
- typename std::enable_if<
- !std::is_convertible<BaseIterator2,BaseIterator>::value&&
- is_constructible<BaseIterator,BaseIterator2>::value
- >::type* =nullptr
- >
- explicit local_iterator_impl(
- const local_iterator_impl<PolyCollection,BaseIterator2>& x):
- local_iterator_impl::iterator_adaptor_{BaseIterator(x.base())},
- mapit{x.mapit}{}
- template<
- typename BaseIterator2,
- typename std::enable_if<
- !is_constructible<BaseIterator,BaseIterator2>::value&&
- is_constructible<BaseIterator,segment_base_iterator>::value&&
- is_constructible<BaseIterator2,segment_base_iterator>::value
- >::type* =nullptr
- >
- explicit local_iterator_impl(
- const local_iterator_impl<PolyCollection,BaseIterator2>& x):
- local_iterator_impl::iterator_adaptor_{
- base_iterator_from(x.segment(),x.base())},
- mapit{x.mapit}{}
- /* define [] to avoid Boost.Iterator operator_brackets_proxy mess */
- template<typename DifferenceType>
- typename std::iterator_traits<BaseIterator>::reference
- operator[](DifferenceType n)const{return *(*this+n);}
- private:
- template<typename,typename>
- friend class local_iterator_impl;
- friend PolyCollection;
- template<typename>
- friend struct iterator_traits;
- template<typename BaseIterator2>
- static BaseIterator base_iterator_from(
- const segment_type& s,BaseIterator2 it)
- {
- segment_base_iterator bit=s.begin();
- return BaseIterator{bit+(it-static_cast<BaseIterator2>(bit))};
- }
- base_iterator base()const noexcept
- {return local_iterator_impl::iterator_adaptor_::base();}
- const std::type_info& type_info()const{return *mapit->first;}
- segment_type& segment()noexcept
- {return const_cast<segment_type&>(mapit->second);}
- const segment_type& segment()const noexcept{return mapit->second;}
- const_segment_map_iterator mapit;
- };
- template<typename PolyCollection,typename BaseIterator>
- struct poly_collection_of<local_iterator_impl<PolyCollection,BaseIterator>>
- {
- using type=PolyCollection;
- };
- } /* namespace poly_collection::detail */
- } /* namespace poly_collection */
- } /* namespace boost */
- #endif
|