zip.hpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_VIEW_ZIP_HPP
  14. #define RANGES_V3_VIEW_ZIP_HPP
  15. #include <tuple>
  16. #include <utility>
  17. #include <meta/meta.hpp>
  18. #include <range/v3/range_fwd.hpp>
  19. #include <range/v3/iterator/concepts.hpp>
  20. #include <range/v3/iterator/traits.hpp>
  21. #include <range/v3/utility/common_tuple.hpp>
  22. #include <range/v3/view/all.hpp>
  23. #include <range/v3/view/empty.hpp>
  24. #include <range/v3/view/zip_with.hpp>
  25. #include <range/v3/detail/prologue.hpp>
  26. namespace ranges
  27. {
  28. /// \cond
  29. namespace detail
  30. {
  31. struct indirect_zip_fn_
  32. {
  33. // tuple value
  34. template(typename... Its)(
  35. requires (sizeof...(Its) != 2) AND and_v<indirectly_readable<Its>...>)
  36. std::tuple<iter_value_t<Its>...> operator()(copy_tag, Its...) const
  37. {
  38. RANGES_EXPECT(false);
  39. }
  40. // tuple reference
  41. template(typename... Its)(
  42. requires (sizeof...(Its) != 2) AND and_v<indirectly_readable<Its>...>)
  43. common_tuple<iter_reference_t<Its>...>
  44. operator()(Its const &... its) const //
  45. noexcept(meta::and_c<noexcept(iter_reference_t<Its>(*its))...>::value)
  46. {
  47. return common_tuple<iter_reference_t<Its>...>{*its...};
  48. }
  49. // tuple rvalue reference
  50. template(typename... Its)(
  51. requires (sizeof...(Its) != 2) AND and_v<indirectly_readable<Its>...>)
  52. common_tuple<iter_rvalue_reference_t<Its>...> //
  53. operator()(move_tag, Its const &... its) const //
  54. noexcept(meta::and_c<noexcept(
  55. iter_rvalue_reference_t<Its>(iter_move(its)))...>::value)
  56. {
  57. return common_tuple<iter_rvalue_reference_t<Its>...>{iter_move(its)...};
  58. }
  59. // pair value
  60. template(typename It1, typename It2)(
  61. requires indirectly_readable<It1> AND indirectly_readable<It2>)
  62. std::pair<iter_value_t<It1>, iter_value_t<It2>> //
  63. operator()(copy_tag, It1, It2) const
  64. {
  65. RANGES_EXPECT(false);
  66. }
  67. // pair reference
  68. template(typename It1, typename It2)(
  69. requires indirectly_readable<It1> AND indirectly_readable<It2>)
  70. common_pair<iter_reference_t<It1>, iter_reference_t<It2>>
  71. operator()(It1 const & it1, It2 const & it2) const //
  72. noexcept( //
  73. noexcept(iter_reference_t<It1>(*it1)) && //
  74. noexcept(iter_reference_t<It2>(*it2)))
  75. {
  76. return {*it1, *it2};
  77. }
  78. // pair rvalue reference
  79. template(typename It1, typename It2)(
  80. requires indirectly_readable<It1> AND indirectly_readable<It2>)
  81. common_pair<iter_rvalue_reference_t<It1>, iter_rvalue_reference_t<It2>>
  82. operator()(move_tag, It1 const & it1, It2 const & it2) const
  83. noexcept(noexcept(iter_rvalue_reference_t<It1>(iter_move(it1))) &&
  84. noexcept(iter_rvalue_reference_t<It2>(iter_move(it2))))
  85. {
  86. return {iter_move(it1), iter_move(it2)};
  87. }
  88. };
  89. } // namespace detail
  90. /// \endcond
  91. /// \addtogroup group-views
  92. /// @{
  93. template<typename... Rngs>
  94. struct zip_view : iter_zip_with_view<detail::indirect_zip_fn_, Rngs...>
  95. {
  96. CPP_assert(sizeof...(Rngs) != 0);
  97. zip_view() = default;
  98. explicit zip_view(Rngs... rngs)
  99. : iter_zip_with_view<detail::indirect_zip_fn_, Rngs...>{
  100. detail::indirect_zip_fn_{},
  101. std::move(rngs)...}
  102. {}
  103. };
  104. template<typename... Rng>
  105. RANGES_INLINE_VAR constexpr bool enable_borrowed_range<zip_view<Rng...>> =
  106. and_v<enable_borrowed_range<Rng>...>;
  107. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  108. template<typename... Rng>
  109. zip_view(Rng &&...) //
  110. -> zip_view<views::all_t<Rng>...>;
  111. #endif
  112. namespace views
  113. {
  114. struct zip_fn
  115. {
  116. constexpr empty_view<std::tuple<>> operator()() const noexcept
  117. {
  118. return {};
  119. }
  120. template(typename... Rngs)(
  121. requires and_v<viewable_range<Rngs>...> AND
  122. and_v<input_range<Rngs>...> AND
  123. (sizeof...(Rngs) != 0)) //
  124. zip_view<all_t<Rngs>...> operator()(Rngs &&... rngs) const
  125. {
  126. return zip_view<all_t<Rngs>...>{all(static_cast<Rngs &&>(rngs))...};
  127. }
  128. #if defined(_MSC_VER)
  129. template(typename Rng0)(
  130. requires input_range<Rng0> AND viewable_range<Rng0>)
  131. constexpr zip_view<all_t<Rng0>> operator()(Rng0 && rng0) const
  132. {
  133. return zip_view<all_t<Rng0>>{all(static_cast<Rng0 &&>(rng0))};
  134. }
  135. template(typename Rng0, typename Rng1)(
  136. requires input_range<Rng0> AND viewable_range<Rng0> AND
  137. input_range<Rng1> AND viewable_range<Rng1>)
  138. constexpr zip_view<all_t<Rng0>, all_t<Rng1>> //
  139. operator()(Rng0 && rng0, Rng1 && rng1) const
  140. {
  141. return zip_view<all_t<Rng0>, all_t<Rng1>>{ //
  142. all(static_cast<Rng0 &&>(rng0)), //
  143. all(static_cast<Rng1 &&>(rng1))};
  144. }
  145. template(typename Rng0, typename Rng1, typename Rng2)(
  146. requires input_range<Rng0> AND viewable_range<Rng0> AND
  147. input_range<Rng1> AND viewable_range<Rng1> AND
  148. input_range<Rng2> AND viewable_range<Rng2>)
  149. constexpr zip_view<all_t<Rng0>, all_t<Rng1>, all_t<Rng2>> //
  150. operator()(Rng0 && rng0, Rng1 && rng1, Rng2 && rng2) const
  151. {
  152. return zip_view<all_t<Rng0>, all_t<Rng1>, all_t<Rng2>>{ //
  153. all(static_cast<Rng0 &&>(rng0)), //
  154. all(static_cast<Rng1 &&>(rng1)), //
  155. all(static_cast<Rng2 &&>(rng2))};
  156. }
  157. #endif
  158. };
  159. /// \relates zip_fn
  160. /// \ingroup group-views
  161. RANGES_INLINE_VARIABLE(zip_fn, zip)
  162. } // namespace views
  163. /// @}
  164. } // namespace ranges
  165. #include <range/v3/detail/satisfy_boost_range.hpp>
  166. RANGES_SATISFY_BOOST_RANGE(::ranges::zip_view)
  167. #include <range/v3/detail/epilogue.hpp>
  168. #endif