conversion.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. // Range v3 library
  2. //
  3. // Copyright Eric Niebler 2014-present
  4. //
  5. // Use, modification and distribution is subject to the
  6. // Boost Software License, Version 1.0. (See accompanying
  7. // file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // Project home: https://github.com/ericniebler/range-v3
  11. #include <list>
  12. #include <map>
  13. #include <vector>
  14. #include <range/v3/action/sort.hpp>
  15. #include <range/v3/core.hpp>
  16. #include <range/v3/range/conversion.hpp>
  17. #include <range/v3/view/indices.hpp>
  18. #include <range/v3/view/iota.hpp>
  19. #include <range/v3/view/take.hpp>
  20. #include <range/v3/view/transform.hpp>
  21. #include <range/v3/view/zip.hpp>
  22. #include <range/v3/view/reverse.hpp>
  23. #include "../simple_test.hpp"
  24. #include "../test_utils.hpp"
  25. template<typename T>
  26. struct vector_like
  27. {
  28. private:
  29. std::vector<T> data_;
  30. public:
  31. using size_type = std::size_t;
  32. using allocator_type = std::allocator<T>;
  33. vector_like() = default;
  34. template<typename I>
  35. vector_like(I first, I last)
  36. : data_(first, last)
  37. {}
  38. template<typename I>
  39. void assign(I first, I last)
  40. {
  41. data_.assign(first, last);
  42. }
  43. auto begin()
  44. {
  45. return data_.begin();
  46. }
  47. auto end()
  48. {
  49. return data_.end();
  50. }
  51. auto begin() const
  52. {
  53. return data_.begin();
  54. }
  55. auto end() const
  56. {
  57. return data_.end();
  58. }
  59. size_type size() const
  60. {
  61. return data_.size();
  62. }
  63. size_type capacity() const
  64. {
  65. return data_.capacity();
  66. }
  67. size_type max_size() const
  68. {
  69. return data_.max_size();
  70. }
  71. auto& operator[](size_type n)
  72. {
  73. return data_[n];
  74. }
  75. auto& operator[](size_type n) const
  76. {
  77. return data_[n];
  78. }
  79. size_type last_reservation{};
  80. size_type reservation_count{};
  81. void reserve(size_type n)
  82. {
  83. data_.reserve(n);
  84. last_reservation = n;
  85. ++reservation_count;
  86. }
  87. };
  88. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  89. template<typename I>
  90. vector_like(I, I) -> vector_like<ranges::iter_value_t<I>>;
  91. template<typename Rng, typename CI = ranges::range_common_iterator_t<Rng>,
  92. typename = decltype(std::map{CI{}, CI{}})>
  93. void test_zip_to_map(Rng && rng, int)
  94. {
  95. using namespace ranges;
  96. #ifdef RANGES_WORKAROUND_MSVC_779708
  97. auto m = static_cast<Rng &&>(rng) | to<std::map>();
  98. #else // ^^^ workaround / no workaround vvv
  99. auto m = static_cast<Rng &&>(rng) | to<std::map>;
  100. #endif // RANGES_WORKAROUND_MSVC_779708
  101. CPP_assert(same_as<decltype(m), std::map<int, int>>);
  102. }
  103. #endif
  104. template<typename Rng>
  105. void test_zip_to_map(Rng &&, long)
  106. {}
  107. template<typename K, typename V>
  108. struct map_like : std::map<K, V>
  109. {
  110. template<typename Iter>
  111. map_like(Iter f, Iter l)
  112. : std::map<K, V>(f, l)
  113. {}
  114. };
  115. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  116. template<typename Iter>
  117. map_like(Iter, Iter) -> map_like<typename ranges::iter_value_t<Iter>::first_type,
  118. typename ranges::iter_value_t<Iter>::second_type>;
  119. #endif
  120. int main()
  121. {
  122. using namespace ranges;
  123. {
  124. auto lst0 = views::ints | views::transform([](int i) { return i * i; }) |
  125. views::take(10) | to<std::list>();
  126. CPP_assert(same_as<decltype(lst0), std::list<int>>);
  127. ::check_equal(lst0, {0, 1, 4, 9, 16, 25, 36, 49, 64, 81});
  128. }
  129. #ifndef RANGES_WORKAROUND_MSVC_779708 // "workaround" is a misnomer; there's no
  130. // workaround.
  131. {
  132. auto lst1 = views::ints | views::transform([](int i) { return i * i; }) |
  133. views::take(10) | to<std::list>;
  134. CPP_assert(same_as<decltype(lst1), std::list<int>>);
  135. ::check_equal(lst1, {0, 1, 4, 9, 16, 25, 36, 49, 64, 81});
  136. }
  137. #endif // RANGES_WORKAROUND_MSVC_779708
  138. {
  139. auto vec0 = views::ints | views::transform([](int i) { return i * i; }) |
  140. views::take(10) | to_vector | actions::sort(std::greater<int>{});
  141. CPP_assert(same_as<decltype(vec0), std::vector<int>>);
  142. ::check_equal(vec0, {81, 64, 49, 36, 25, 16, 9, 4, 1, 0});
  143. }
  144. {
  145. auto vec1 = views::ints | views::transform([](int i) { return i * i; }) |
  146. views::take(10) | to<std::vector<long>>() |
  147. actions::sort(std::greater<long>{});
  148. CPP_assert(same_as<decltype(vec1), std::vector<long>>);
  149. ::check_equal(vec1, {81, 64, 49, 36, 25, 16, 9, 4, 1, 0});
  150. }
  151. #ifndef RANGES_WORKAROUND_MSVC_779708
  152. {
  153. auto vec2 = views::ints | views::transform([](int i) { return i * i; }) |
  154. views::take(10) | to<std::vector<long>> |
  155. actions::sort(std::greater<long>{});
  156. CPP_assert(same_as<decltype(vec2), std::vector<long>>);
  157. ::check_equal(vec2, {81, 64, 49, 36, 25, 16, 9, 4, 1, 0});
  158. }
  159. #endif // RANGES_WORKAROUND_MSVC_779708
  160. {
  161. const std::size_t N = 4096;
  162. auto vl = views::iota(0, int{N}) | to<vector_like<int>>();
  163. CPP_assert(same_as<decltype(vl), vector_like<int>>);
  164. CHECK(vl.reservation_count == std::size_t{1});
  165. CHECK(vl.last_reservation == N);
  166. }
  167. // https://github.com/ericniebler/range-v3/issues/1145
  168. {
  169. auto r1 = views::indices(std::uintmax_t{100});
  170. auto r2 = views::zip(r1, r1);
  171. #ifdef RANGES_WORKAROUND_MSVC_779708
  172. auto m = r2 | ranges::to<std::map<std::uintmax_t, std::uintmax_t>>();
  173. #else // ^^^ workaround / no workaround vvv
  174. auto m = r2 | ranges::to<std::map<std::uintmax_t, std::uintmax_t>>;
  175. #endif // RANGES_WORKAROUND_MSVC_779708
  176. CPP_assert(same_as<decltype(m), std::map<std::uintmax_t, std::uintmax_t>>);
  177. }
  178. // Transform a range-of-ranges into a container of containers
  179. {
  180. auto r = views::ints(1, 4) |
  181. views::transform([](int i) { return views::ints(i, i + 3); });
  182. auto m = r | ranges::to<std::vector<std::vector<int>>>();
  183. CPP_assert(same_as<decltype(m), std::vector<std::vector<int>>>);
  184. CHECK(m.size() == 3u);
  185. check_equal(m[0], {1, 2, 3});
  186. check_equal(m[1], {2, 3, 4});
  187. check_equal(m[2], {3, 4, 5});
  188. }
  189. // Use ranges::to in a closure with an action
  190. {
  191. #ifdef RANGES_WORKAROUND_MSVC_779708
  192. auto closure = ranges::to<std::vector>() | actions::sort;
  193. #else // ^^^ workaround / no workaround vvv
  194. auto closure = ranges::to<std::vector> | actions::sort;
  195. #endif // RANGES_WORKAROUND_MSVC_779708
  196. auto r = views::ints(1, 4) | views::reverse;
  197. auto m = r | closure;
  198. CPP_assert(same_as<decltype(m), std::vector<int>>);
  199. CHECK(m.size() == 3u);
  200. check_equal(m, {1, 2, 3});
  201. }
  202. test_zip_to_map(views::zip(views::ints, views::iota(0, 10)), 0);
  203. // https://github.com/ericniebler/range-v3/issues/1544
  204. {
  205. std::vector<std::vector<int>> d;
  206. auto m = views::transform(d, views::all);
  207. auto v = ranges::to<std::vector<std::vector<int>>>(m);
  208. check_equal(d, v);
  209. }
  210. {
  211. std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}};
  212. auto m1 = ranges::to<map_like<int, int>>(v);
  213. auto m2 = v | ranges::to<map_like<int, int>>();
  214. CPP_assert(same_as<decltype(m1), map_like<int, int>>);
  215. CPP_assert(same_as<decltype(m2), map_like<int, int>>);
  216. check_equal(m1, std::map<int, int>{{1, 2}, {3, 4}});
  217. check_equal(m1, m2);
  218. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  219. auto m3 = ranges::to<map_like>(v);
  220. auto m4 = v | ranges::to<map_like>();
  221. CPP_assert(same_as<decltype(m3), map_like<int, int>>);
  222. CPP_assert(same_as<decltype(m4), map_like<int, int>>);
  223. check_equal(m1, m3);
  224. check_equal(m1, m4);
  225. #endif
  226. }
  227. return ::test_result();
  228. }