/* Copyright 2016-2017 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 #include #include #include #include #include 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 using iterator_impl_value_type=typename std::conditional< Const, const typename PolyCollection::value_type, typename PolyCollection::value_type >::type; template class iterator_impl: public boost::iterator_facade< iterator_impl, iterator_impl_value_type, 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; 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::type* =nullptr> iterator_impl(const iterator_impl& x): mapit{x.mapit},mapend{x.mapend},segpos{x.segpos}{} private: template friend class iterator_impl; friend PolyCollection; friend class boost::iterator_core_access; template friend struct iterator_traits; value_type& dereference()const noexcept {return const_cast(*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(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 struct poly_collection_of> { using type=PolyCollection; }; template class local_iterator_impl: public boost::iterator_adaptor< local_iterator_impl, 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; template 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::value >::type* =nullptr > local_iterator_impl( const local_iterator_impl& x): local_iterator_impl::iterator_adaptor_{x.base()}, mapit{x.mapit}{} template< typename BaseIterator2, typename std::enable_if< !std::is_convertible::value&& is_constructible::value >::type* =nullptr > explicit local_iterator_impl( const local_iterator_impl& x): local_iterator_impl::iterator_adaptor_{BaseIterator(x.base())}, mapit{x.mapit}{} template< typename BaseIterator2, typename std::enable_if< !is_constructible::value&& is_constructible::value&& is_constructible::value >::type* =nullptr > explicit local_iterator_impl( const local_iterator_impl& 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 std::iterator_traits::reference operator[](DifferenceType n)const{return *(*this+n);} private: template friend class local_iterator_impl; friend PolyCollection; template friend struct iterator_traits; template static BaseIterator base_iterator_from( const segment_type& s,BaseIterator2 it) { segment_base_iterator bit=s.begin(); return BaseIterator{bit+(it-static_cast(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(mapit->second);} const segment_type& segment()const noexcept{return mapit->second;} const_segment_map_iterator mapit; }; template struct poly_collection_of> { using type=PolyCollection; }; } /* namespace poly_collection::detail */ } /* namespace poly_collection */ } /* namespace boost */ #endif