join.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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 <iterator>
  12. #include <forward_list>
  13. #include <functional>
  14. #include <vector>
  15. #include <range/v3/core.hpp>
  16. #include <range/v3/view/join.hpp>
  17. #include <range/v3/view/split.hpp>
  18. #include <range/v3/view/generate_n.hpp>
  19. #include <range/v3/view/repeat_n.hpp>
  20. #include <range/v3/view/chunk.hpp>
  21. #include <range/v3/view/concat.hpp>
  22. #include <range/v3/view/iota.hpp>
  23. #include <range/v3/view/single.hpp>
  24. #include <range/v3/view/transform.hpp>
  25. #include <range/v3/view/filter.hpp>
  26. #include "../simple_test.hpp"
  27. #include "../test_utils.hpp"
  28. #include "../test_iterators.hpp"
  29. RANGES_DIAGNOSTIC_IGNORE_GLOBAL_CONSTRUCTORS
  30. namespace
  31. {
  32. template<typename T, std::size_t N>
  33. struct input_array
  34. {
  35. T elements_[N];
  36. InputIterator<T*> begin() { return InputIterator<T*>{elements_ + 0}; }
  37. InputIterator<T*> end() { return InputIterator<T*>{elements_ + N}; }
  38. constexpr std::size_t size() const { return N; }
  39. };
  40. static int N = 0;
  41. auto make_input_rng()
  42. {
  43. using ranges::views::generate_n;
  44. return generate_n([](){
  45. return generate_n([](){
  46. return N++;
  47. },3);
  48. },3);
  49. }
  50. template<typename T>
  51. constexpr auto twice(T t)
  52. {
  53. return ranges::views::concat(
  54. ranges::views::single(t),
  55. ranges::views::single(t));
  56. }
  57. #ifdef __clang__
  58. RANGES_DIAGNOSTIC_IGNORE_PRAGMAS
  59. RANGES_DIAGNOSTIC_IGNORE("-Wunneeded-member-function")
  60. RANGES_DIAGNOSTIC_IGNORE("-Wunused-member-function")
  61. #endif
  62. // https://github.com/ericniebler/range-v3/issues/283
  63. void test_issue_283()
  64. {
  65. const std::vector<std::vector<int>> nums =
  66. {
  67. { 1, 2, 3 },
  68. { 4, 5, 6 }
  69. };
  70. const auto flat_nums = ranges::views::join( nums ) | ranges::to<std::vector>();
  71. ::check_equal(flat_nums, {1,2,3,4,5,6});
  72. }
  73. // https://github.com/ericniebler/range-v3/issues/1414
  74. void test_issue_1414()
  75. {
  76. std::forward_list<char> u2; // this can also be a vector
  77. std::vector<char> i2;
  78. auto v2 = u2 | ranges::views::chunk(3) | ranges::views::join(i2);
  79. CPP_assert(ranges::input_range<decltype(v2)>);
  80. }
  81. }
  82. int main()
  83. {
  84. using namespace ranges;
  85. // Test that we can join an input range of input ranges:
  86. {
  87. auto rng0 = make_input_rng() | views::join;
  88. static_assert(range_cardinality<decltype(rng0)>::value == ranges::finite, "");
  89. CPP_assert(input_range<decltype(rng0)>);
  90. CPP_assert(!forward_range<decltype(rng0)>);
  91. CPP_assert(!common_range<decltype(rng0)>);
  92. CPP_assert(!sized_range<decltype(rng0)>);
  93. check_equal(rng0, {0,1,2,3,4,5,6,7,8});
  94. }
  95. // Joining with a value
  96. {
  97. N = 0;
  98. auto rng1 = make_input_rng() | views::join(42);
  99. static_assert(range_cardinality<decltype(rng1)>::value == ranges::finite, "");
  100. CPP_assert(input_range<decltype(rng1)>);
  101. CPP_assert(!forward_range<decltype(rng1)>);
  102. CPP_assert(!common_range<decltype(rng1)>);
  103. CPP_assert(!sized_range<decltype(rng1)>);
  104. check_equal(rng1, {0,1,2,42,3,4,5,42,6,7,8});
  105. }
  106. // Joining with a range
  107. {
  108. N = 0;
  109. int rgi[] = {42,43};
  110. auto rng2 = make_input_rng() | views::join(rgi);
  111. static_assert(range_cardinality<decltype(rng2)>::value == ranges::finite, "");
  112. CPP_assert(input_range<decltype(rng2)>);
  113. CPP_assert(!forward_range<decltype(rng2)>);
  114. CPP_assert(!common_range<decltype(rng2)>);
  115. CPP_assert(!sized_range<decltype(rng2)>);
  116. check_equal(rng2, {0,1,2,42,43,3,4,5,42,43,6,7,8});
  117. }
  118. // Just for fun:
  119. {
  120. std::string str = "Now,is,the,time,for,all,good,men,to,come,to,the,aid,of,their,country";
  121. auto res = str | views::split(',') | views::join(' ') | to<std::string>();
  122. CHECK(res == "Now is the time for all good men to come to the aid of their country");
  123. static_assert(range_cardinality<decltype(res)>::value == ranges::finite, "");
  124. }
  125. {
  126. std::vector<std::string> vs{"This","is","his","face"};
  127. auto rng3 = views::join(vs);
  128. static_assert(range_cardinality<decltype(rng3)>::value == ranges::finite, "");
  129. CPP_assert(!sized_range<decltype(rng3)>);
  130. CPP_assert(!sized_sentinel_for<decltype(end(rng3)), decltype(begin(rng3))>);
  131. CHECK(to<std::string>(rng3) == "Thisishisface");
  132. auto rng4 = views::join(vs, ' ');
  133. static_assert(range_cardinality<decltype(rng3)>::value == ranges::finite, "");
  134. CPP_assert(!sized_range<decltype(rng4)>);
  135. CPP_assert(!sized_sentinel_for<decltype(end(rng4)), decltype(begin(rng4))>);
  136. CHECK(to<std::string>(rng4) == "This is his face");
  137. }
  138. {
  139. auto rng5 = views::join(twice(twice(42)));
  140. static_assert(range_cardinality<decltype(rng5)>::value == 4, "");
  141. CPP_assert(sized_range<decltype(rng5)>);
  142. CHECK(rng5.size() == 4u);
  143. check_equal(rng5, {42,42,42,42});
  144. }
  145. {
  146. auto rng6 = views::join(twice(views::repeat_n(42, 2)));
  147. static_assert(range_cardinality<decltype(rng6)>::value == ranges::finite, "");
  148. CPP_assert(sized_range<decltype(rng6)>);
  149. CHECK(rng6.size() == 4u);
  150. check_equal(rng6, {42,42,42,42});
  151. }
  152. {
  153. input_array<std::string, 4> some_strings = {{"This","is","his","face"}};
  154. CPP_assert(input_range<decltype(some_strings)>);
  155. CPP_assert(sized_range<decltype(some_strings)>);
  156. CPP_assert(!sized_range<decltype(some_strings | views::join)>);
  157. }
  158. {
  159. int const some_int_pairs[3][2] = {{0,1},{2,3},{4,5}};
  160. auto rng = debug_input_view<int const[2]>{some_int_pairs} | views::join;
  161. check_equal(rng, {0,1,2,3,4,5});
  162. }
  163. {
  164. std::vector<std::string> vs{"this","is","his","face"};
  165. join_view<ref_view<std::vector<std::string>>> jv{vs};
  166. check_equal(jv, {'t','h','i','s','i','s','h','i','s','f','a','c','e'});
  167. CPP_assert(bidirectional_range<decltype(jv)>);
  168. CPP_assert(bidirectional_range<const decltype(jv)>);
  169. CPP_assert(common_range<decltype(jv)>);
  170. CPP_assert(common_range<const decltype(jv)>);
  171. }
  172. {
  173. auto rng = views::iota(0,4)
  174. | views::transform([](int i) {return views::iota(0,i);})
  175. | views::join;
  176. check_equal(rng, {0,0,1,0,1,2});
  177. CPP_assert(input_range<decltype(rng)>);
  178. CPP_assert(!range<const decltype(rng)>);
  179. CPP_assert(!forward_range<decltype(rng)>);
  180. CPP_assert(!common_range<decltype(rng)>);
  181. }
  182. {
  183. auto rng = views::iota(0,4)
  184. | views::transform([](int i) {return views::iota(0,i);})
  185. | views::filter([](auto){ return true; })
  186. | views::join;
  187. check_equal(rng, {0,0,1,0,1,2});
  188. CPP_assert(input_range<decltype(rng)>);
  189. CPP_assert(!range<const decltype(rng)>);
  190. CPP_assert(!forward_range<decltype(rng)>);
  191. CPP_assert(!common_range<decltype(rng)>);
  192. }
  193. {
  194. auto rng = views::iota(0,4)
  195. | views::transform([](int i) {return std::string((std::size_t) i, char('a'+i));})
  196. | views::join;
  197. check_equal(rng, {'b','c','c','d','d','d'});
  198. CPP_assert(input_range<decltype(rng)>);
  199. CPP_assert(!range<const decltype(rng)>);
  200. CPP_assert(!forward_range<decltype(rng)>);
  201. CPP_assert(!common_range<decltype(rng)>);
  202. }
  203. {
  204. auto rng = views::iota(0,4)
  205. | views::transform([](int i) {return std::string((std::size_t) i, char('a'+i));})
  206. | views::join('-');
  207. check_equal(rng, {'-','b','-','c','c','-','d','d','d'});
  208. CPP_assert(input_range<decltype(rng)>);
  209. CPP_assert(!range<const decltype(rng)>);
  210. CPP_assert(!forward_range<decltype(rng)>);
  211. CPP_assert(!common_range<decltype(rng)>);
  212. }
  213. // https://github.com/ericniebler/range-v3/issues/1320
  214. {
  215. auto op = [](auto & input, int i, auto & ins)
  216. {
  217. return input | ranges::views::chunk(i)
  218. | ranges::views::join(ins);
  219. };
  220. std::string input{"foobarbaxbat"};
  221. std::string insert{"X"};
  222. auto rng = op(input, 2, insert);
  223. std::cout << rng << '\n';
  224. ::check_equal(rng, {'f','o','X','o','b','X','a','r','X','b','a','X','x','b','X',
  225. 'a','t'});
  226. }
  227. {
  228. auto op = [](auto & input, int i, auto & ins)
  229. {
  230. return input | ranges::views::chunk(i)
  231. | ranges::views::join(ins);
  232. };
  233. std::vector<std::string> input{"foo","bar","bax","bat"};
  234. std::string insert{"XX"};
  235. auto rng = op(input, 2, insert);
  236. std::cout << rng << '\n';
  237. ::check_equal(rng, {"foo","bar","XX","bax","bat"});
  238. }
  239. test_issue_283();
  240. test_issue_1414();
  241. return ::test_result();
  242. }