combine.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. // Copyright Neil Groves 2010. Use, modification and
  2. // distribution is subject to the Boost Software License, Version
  3. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. //
  6. //
  7. // For more information, see http://www.boost.org/libs/range/
  8. //
  9. #ifndef BOOST_RANGE_COMBINE_HPP
  10. #define BOOST_RANGE_COMBINE_HPP
  11. #include <boost/iterator/zip_iterator.hpp>
  12. #include <boost/tuple/tuple.hpp>
  13. #include <boost/range/iterator.hpp>
  14. #include <boost/range/iterator_range.hpp>
  15. #include <boost/type_traits/is_void.hpp>
  16. #include <boost/type_traits/is_same.hpp>
  17. #include <boost/mpl/eval_if.hpp>
  18. #include <boost/mpl/int.hpp>
  19. #include <boost/mpl/plus.hpp>
  20. #include <boost/mpl/arithmetic.hpp>
  21. #include <boost/config.hpp>
  22. namespace boost
  23. {
  24. namespace range_detail
  25. {
  26. struct void_ { typedef void_ type; };
  27. }
  28. template<> struct range_iterator< ::boost::range_detail::void_ >
  29. {
  30. typedef ::boost::tuples::null_type type;
  31. };
  32. namespace range_detail
  33. {
  34. inline ::boost::tuples::null_type range_begin( ::boost::range_detail::void_& )
  35. { return ::boost::tuples::null_type(); }
  36. inline ::boost::tuples::null_type range_begin( const ::boost::range_detail::void_& )
  37. { return ::boost::tuples::null_type(); }
  38. inline ::boost::tuples::null_type range_end( ::boost::range_detail::void_& )
  39. { return ::boost::tuples::null_type(); }
  40. inline ::boost::tuples::null_type range_end( const ::boost::range_detail::void_& )
  41. { return ::boost::tuples::null_type(); }
  42. template< class T >
  43. struct tuple_iter
  44. {
  45. typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::eval_if_c<
  46. ::boost::is_same<T, ::boost::range_detail::void_ >::value,
  47. ::boost::mpl::identity< ::boost::tuples::null_type >,
  48. ::boost::range_iterator<T>
  49. >::type type;
  50. };
  51. template< class Rng1, class Rng2 >
  52. struct tuple_range
  53. {
  54. typedef BOOST_DEDUCED_TYPENAME ::boost::mpl::eval_if_c<
  55. ::boost::is_same<Rng1, ::boost::range_detail::void_ >::value,
  56. ::boost::range_detail::void_,
  57. ::boost::mpl::identity<Rng1>
  58. >::type type;
  59. };
  60. template
  61. <
  62. class R1,
  63. class R2,
  64. class R3,
  65. class R4,
  66. class R5,
  67. class R6
  68. >
  69. struct generate_tuple
  70. {
  71. typedef ::boost::tuples::tuple<
  72. BOOST_DEDUCED_TYPENAME tuple_iter<R1>::type,
  73. BOOST_DEDUCED_TYPENAME tuple_iter<R2>::type,
  74. BOOST_DEDUCED_TYPENAME tuple_iter<R3>::type,
  75. BOOST_DEDUCED_TYPENAME tuple_iter<R4>::type,
  76. BOOST_DEDUCED_TYPENAME tuple_iter<R5>::type,
  77. BOOST_DEDUCED_TYPENAME tuple_iter<R6>::type
  78. > type;
  79. static type begin( R1& r1, R2& r2, R3& r3, R4& r4, R5& r5, R6& r6 )
  80. {
  81. return ::boost::tuples::make_tuple( ::boost::begin(r1),
  82. ::boost::begin(r2),
  83. ::boost::begin(r3),
  84. ::boost::begin(r4),
  85. ::boost::begin(r5),
  86. ::boost::begin(r6) );
  87. }
  88. static type end( R1& r1, R2& r2, R3& r3, R4& r4, R5& r5, R6& r6 )
  89. {
  90. return ::boost::tuples::make_tuple( ::boost::end(r1),
  91. ::boost::end(r2),
  92. ::boost::end(r3),
  93. ::boost::end(r4),
  94. ::boost::end(r5),
  95. ::boost::end(r6) );
  96. }
  97. };
  98. template
  99. <
  100. class R1,
  101. class R2 = void_,
  102. class R3 = void_,
  103. class R4 = void_,
  104. class R5 = void_,
  105. class R6 = void_
  106. >
  107. struct zip_rng
  108. : iterator_range<
  109. zip_iterator<
  110. BOOST_DEDUCED_TYPENAME generate_tuple<R1,R2,R3,R4,R5,R6>::type
  111. >
  112. >
  113. {
  114. private:
  115. typedef generate_tuple<R1,R2,R3,R4,R5,R6> generator_t;
  116. typedef BOOST_DEDUCED_TYPENAME generator_t::type tuple_t;
  117. typedef zip_iterator<tuple_t> zip_iter_t;
  118. typedef iterator_range<zip_iter_t> base_t;
  119. public:
  120. zip_rng( R1& r1, R2& r2, R3& r3, R4& r4, R5& r5, R6& r6 )
  121. : base_t( zip_iter_t( generator_t::begin(r1,r2,r3,r4,r5,r6) ),
  122. zip_iter_t( generator_t::end(r1,r2,r3,r4,r5,r6) ) )
  123. {
  124. BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r2));
  125. BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r3));
  126. BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r4));
  127. BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r5));
  128. BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r6));
  129. }
  130. template< class Zip, class Rng >
  131. zip_rng( Zip& z, Rng& r )
  132. : base_t( zip_iter_t( generator_t::begin( z, r ) ),
  133. zip_iter_t( generator_t::end( z, r ) ) )
  134. {
  135. // @todo: tuple::begin( should be overloaded for this situation
  136. }
  137. struct tuple_length : ::boost::tuples::length<tuple_t>
  138. { };
  139. template< unsigned N >
  140. struct get
  141. {
  142. template< class Z, class R >
  143. static BOOST_DEDUCED_TYPENAME ::boost::tuples::element<N,tuple_t>::type begin( Z& z, R& )
  144. {
  145. return get<N>( z.begin().get_iterator_tuple() );
  146. }
  147. template< class Z, class R >
  148. static BOOST_DEDUCED_TYPENAME ::boost::tuples::element<N,tuple_t>::type end( Z& z, R& r )
  149. {
  150. return get<N>( z.end().get_iterator_tuple() );
  151. }
  152. };
  153. };
  154. template< class Rng1, class Rng2 >
  155. struct zip_range
  156. : iterator_range<
  157. zip_iterator<
  158. ::boost::tuples::tuple<
  159. BOOST_DEDUCED_TYPENAME ::boost::range_iterator<Rng1>::type,
  160. BOOST_DEDUCED_TYPENAME ::boost::range_iterator<Rng2>::type
  161. >
  162. >
  163. >
  164. {
  165. private:
  166. typedef zip_iterator<
  167. ::boost::tuples::tuple<
  168. BOOST_DEDUCED_TYPENAME ::boost::range_iterator<Rng1>::type,
  169. BOOST_DEDUCED_TYPENAME ::boost::range_iterator<Rng2>::type
  170. >
  171. > zip_iter_t;
  172. typedef iterator_range<zip_iter_t> base_t;
  173. public:
  174. zip_range( Rng1& r1, Rng2& r2 )
  175. : base_t( zip_iter_t( ::boost::tuples::make_tuple(::boost::begin(r1),
  176. ::boost::begin(r2)) ),
  177. zip_iter_t( ::boost::tuples::make_tuple(::boost::end(r1),
  178. ::boost::end(r2)) ) )
  179. {
  180. BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r2));
  181. }
  182. };
  183. template< class Rng1, class Rng2, class Rng3 >
  184. struct zip_range3
  185. : iterator_range<
  186. zip_iterator<
  187. ::boost::tuples::tuple<
  188. BOOST_DEDUCED_TYPENAME ::boost::range_iterator<Rng1>::type,
  189. BOOST_DEDUCED_TYPENAME ::boost::range_iterator<Rng2>::type,
  190. BOOST_DEDUCED_TYPENAME ::boost::range_iterator<Rng3>::type
  191. >
  192. >
  193. >
  194. {
  195. private:
  196. typedef zip_iterator<
  197. ::boost::tuples::tuple<
  198. BOOST_DEDUCED_TYPENAME ::boost::range_iterator<Rng1>::type,
  199. BOOST_DEDUCED_TYPENAME ::boost::range_iterator<Rng2>::type,
  200. BOOST_DEDUCED_TYPENAME ::boost::range_iterator<Rng3>::type
  201. >
  202. > zip_iter_t;
  203. typedef iterator_range<zip_iter_t> base_t;
  204. public:
  205. zip_range3( Rng1& r1, Rng2& r2, Rng3& r3 )
  206. : base_t( zip_iter_t( ::boost::tuples::make_tuple(::boost::begin(r1),
  207. ::boost::begin(r2),
  208. ::boost::begin(r3)) ),
  209. zip_iter_t( ::boost::tuples::make_tuple(::boost::end(r1),
  210. ::boost::end(r2),
  211. ::boost::end(r3)) )
  212. )
  213. {
  214. BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r2));
  215. BOOST_ASSERT(::boost::distance(r1) <= ::boost::distance(r3));
  216. }
  217. };
  218. struct combine_tag {};
  219. template< class Rng >
  220. inline zip_rng<Rng>
  221. operator&( combine_tag, Rng& r )
  222. {
  223. return zip_rng<Rng>(r);
  224. }
  225. template< class Rng >
  226. inline iterator_range<const Rng>
  227. operator&( combine_tag, const Rng& r )
  228. {
  229. return iterator_range<const Rng>(r);
  230. }
  231. template
  232. <
  233. class R1,
  234. class R2,
  235. class R3,
  236. class R4,
  237. class R5,
  238. class Rng
  239. >
  240. inline BOOST_DEDUCED_TYPENAME zip_rng<R1,R2,R3,R4,R5>::next
  241. operator&( const zip_rng<R1,R2,R3,R4,R5>& zip,
  242. Rng& r )
  243. {
  244. return zip_rng<R1,R2,R3,R4,R5>::next( zip, r );
  245. }
  246. } // namespace range_detail
  247. template< class Rng1, class Rng2 >
  248. inline ::boost::range_detail::zip_range<Rng1, Rng2> combine( Rng1& r1, Rng2& r2 )
  249. {
  250. return ::boost::range_detail::zip_range<Rng1, Rng2>(r1, r2);
  251. }
  252. template< class Rng1, class Rng2 >
  253. inline ::boost::range_detail::zip_range<const Rng1, Rng2> combine( const Rng1& r1, Rng2& r2 )
  254. {
  255. return ::boost::range_detail::zip_range<const Rng1, Rng2>(r1, r2);
  256. }
  257. template< class Rng1, class Rng2 >
  258. inline ::boost::range_detail::zip_range<Rng1, const Rng2> combine( Rng1& r1, const Rng2& r2 )
  259. {
  260. return ::boost::range_detail::zip_range<Rng1, const Rng2>(r1, r2);
  261. }
  262. template< class Rng1, class Rng2 >
  263. inline ::boost::range_detail::zip_range<const Rng1, const Rng2> combine( const Rng1& r1, const Rng2& r2 )
  264. {
  265. return ::boost::range_detail::zip_range<const Rng1, const Rng2>(r1, r2);
  266. }
  267. } // namespace boost
  268. #endif