iterator_impl.hpp 7.1 KB

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