iterator_impl.hpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /* Copyright 2016-2017 Joaquin M Lopez Munoz.
  2. * Distributed under the Boost Software License, Version 1.0.
  3. * (See accompanying file LICENSE_1_0.txt or copy at
  4. * http://www.boost.org/LICENSE_1_0.txt)
  5. *
  6. * See http://www.boost.org/libs/poly_collection for library home page.
  7. */
  8. #ifndef BOOST_POLY_COLLECTION_DETAIL_ITERATOR_IMPL_HPP
  9. #define BOOST_POLY_COLLECTION_DETAIL_ITERATOR_IMPL_HPP
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/iterator/iterator_adaptor.hpp>
  14. #include <boost/iterator/iterator_facade.hpp>
  15. #include <boost/poly_collection/detail/is_constructible.hpp>
  16. #include <boost/poly_collection/detail/iterator_traits.hpp>
  17. #include <type_traits>
  18. #include <typeinfo>
  19. namespace boost{
  20. namespace poly_collection{
  21. namespace detail{
  22. /* Implementations of poly_collection::[const_][local_[base_]]iterator moved
  23. * out of class to allow for use in deduced contexts.
  24. */
  25. template<typename PolyCollection,bool Const>
  26. using iterator_impl_value_type=typename std::conditional<
  27. Const,
  28. const typename PolyCollection::value_type,
  29. typename PolyCollection::value_type
  30. >::type;
  31. template<typename PolyCollection,bool Const>
  32. class iterator_impl:
  33. public boost::iterator_facade<
  34. iterator_impl<PolyCollection,Const>,
  35. iterator_impl_value_type<PolyCollection,Const>,
  36. boost::forward_traversal_tag
  37. >
  38. {
  39. using segment_type=typename PolyCollection::segment_type;
  40. using const_segment_base_iterator=
  41. typename PolyCollection::const_segment_base_iterator;
  42. using const_segment_base_sentinel=
  43. typename PolyCollection::const_segment_base_sentinel;
  44. using const_segment_map_iterator=
  45. typename PolyCollection::const_segment_map_iterator;
  46. public:
  47. using value_type=iterator_impl_value_type<PolyCollection,Const>;
  48. private:
  49. iterator_impl(
  50. const_segment_map_iterator mapit,
  51. const_segment_map_iterator mapend)noexcept:
  52. mapit{mapit},mapend{mapend}
  53. {
  54. next_segment_position();
  55. }
  56. iterator_impl(
  57. const_segment_map_iterator mapit_,const_segment_map_iterator mapend_,
  58. const_segment_base_iterator segpos_)noexcept:
  59. mapit{mapit_},mapend{mapend_},segpos{segpos_}
  60. {
  61. if(mapit!=mapend&&segpos==sentinel()){
  62. ++mapit;
  63. next_segment_position();
  64. }
  65. }
  66. public:
  67. iterator_impl()=default;
  68. iterator_impl(const iterator_impl&)=default;
  69. iterator_impl& operator=(const iterator_impl&)=default;
  70. template<bool Const2,typename std::enable_if<!Const2>::type* =nullptr>
  71. iterator_impl(const iterator_impl<PolyCollection,Const2>& x):
  72. mapit{x.mapit},mapend{x.mapend},segpos{x.segpos}{}
  73. private:
  74. template<typename,bool>
  75. friend class iterator_impl;
  76. friend PolyCollection;
  77. friend class boost::iterator_core_access;
  78. template<typename>
  79. friend struct iterator_traits;
  80. value_type& dereference()const noexcept
  81. {return const_cast<value_type&>(*segpos);}
  82. bool equal(const iterator_impl& x)const noexcept{return segpos==x.segpos;}
  83. void increment()noexcept
  84. {
  85. if(++segpos==sentinel()){
  86. ++mapit;
  87. next_segment_position();
  88. }
  89. }
  90. void next_segment_position()noexcept
  91. {
  92. for(;mapit!=mapend;++mapit){
  93. segpos=segment().begin();
  94. if(segpos!=sentinel())return;
  95. }
  96. segpos=nullptr;
  97. }
  98. segment_type& segment()noexcept
  99. {return const_cast<segment_type&>(mapit->second);}
  100. const segment_type& segment()const noexcept{return mapit->second;}
  101. const_segment_base_sentinel sentinel()const noexcept
  102. {return segment().sentinel();}
  103. const_segment_map_iterator mapit,mapend;
  104. const_segment_base_iterator segpos;
  105. };
  106. template<typename PolyCollection,bool Const>
  107. struct poly_collection_of<iterator_impl<PolyCollection,Const>>
  108. {
  109. using type=PolyCollection;
  110. };
  111. template<typename PolyCollection,typename BaseIterator>
  112. class local_iterator_impl:
  113. public boost::iterator_adaptor<
  114. local_iterator_impl<PolyCollection,BaseIterator>,
  115. BaseIterator
  116. >
  117. {
  118. using segment_type=typename PolyCollection::segment_type;
  119. using segment_base_iterator=typename PolyCollection::segment_base_iterator;
  120. using const_segment_map_iterator=
  121. typename PolyCollection::const_segment_map_iterator;
  122. template<typename Iterator>
  123. local_iterator_impl(
  124. const_segment_map_iterator mapit,
  125. Iterator it):
  126. local_iterator_impl::iterator_adaptor_{BaseIterator(it)},
  127. mapit{mapit}
  128. {}
  129. public:
  130. using base_iterator=BaseIterator;
  131. local_iterator_impl()=default;
  132. local_iterator_impl(const local_iterator_impl&)=default;
  133. local_iterator_impl& operator=(const local_iterator_impl&)=default;
  134. template<
  135. typename BaseIterator2,
  136. typename std::enable_if<
  137. std::is_convertible<BaseIterator2,BaseIterator>::value
  138. >::type* =nullptr
  139. >
  140. local_iterator_impl(
  141. const local_iterator_impl<PolyCollection,BaseIterator2>& x):
  142. local_iterator_impl::iterator_adaptor_{x.base()},
  143. mapit{x.mapit}{}
  144. template<
  145. typename BaseIterator2,
  146. typename std::enable_if<
  147. !std::is_convertible<BaseIterator2,BaseIterator>::value&&
  148. is_constructible<BaseIterator,BaseIterator2>::value
  149. >::type* =nullptr
  150. >
  151. explicit local_iterator_impl(
  152. const local_iterator_impl<PolyCollection,BaseIterator2>& x):
  153. local_iterator_impl::iterator_adaptor_{BaseIterator(x.base())},
  154. mapit{x.mapit}{}
  155. template<
  156. typename BaseIterator2,
  157. typename std::enable_if<
  158. !is_constructible<BaseIterator,BaseIterator2>::value&&
  159. is_constructible<BaseIterator,segment_base_iterator>::value&&
  160. is_constructible<BaseIterator2,segment_base_iterator>::value
  161. >::type* =nullptr
  162. >
  163. explicit local_iterator_impl(
  164. const local_iterator_impl<PolyCollection,BaseIterator2>& x):
  165. local_iterator_impl::iterator_adaptor_{
  166. base_iterator_from(x.segment(),x.base())},
  167. mapit{x.mapit}{}
  168. /* define [] to avoid Boost.Iterator operator_brackets_proxy mess */
  169. template<typename DifferenceType>
  170. typename std::iterator_traits<BaseIterator>::reference
  171. operator[](DifferenceType n)const{return *(*this+n);}
  172. private:
  173. template<typename,typename>
  174. friend class local_iterator_impl;
  175. friend PolyCollection;
  176. template<typename>
  177. friend struct iterator_traits;
  178. template<typename BaseIterator2>
  179. static BaseIterator base_iterator_from(
  180. const segment_type& s,BaseIterator2 it)
  181. {
  182. segment_base_iterator bit=s.begin();
  183. return BaseIterator{bit+(it-static_cast<BaseIterator2>(bit))};
  184. }
  185. base_iterator base()const noexcept
  186. {return local_iterator_impl::iterator_adaptor_::base();}
  187. const std::type_info& type_info()const{return *mapit->first;}
  188. segment_type& segment()noexcept
  189. {return const_cast<segment_type&>(mapit->second);}
  190. const segment_type& segment()const noexcept{return mapit->second;}
  191. const_segment_map_iterator mapit;
  192. };
  193. template<typename PolyCollection,typename BaseIterator>
  194. struct poly_collection_of<local_iterator_impl<PolyCollection,BaseIterator>>
  195. {
  196. using type=PolyCollection;
  197. };
  198. } /* namespace poly_collection::detail */
  199. } /* namespace poly_collection */
  200. } /* namespace boost */
  201. #endif