any_view.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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 <map>
  12. #include <vector>
  13. #include <range/v3/core.hpp>
  14. #include <range/v3/utility/copy.hpp>
  15. #include <range/v3/view/any_view.hpp>
  16. #include <range/v3/view/iota.hpp>
  17. #include <range/v3/view/map.hpp>
  18. #include <range/v3/view/reverse.hpp>
  19. #include <range/v3/view/tail.hpp>
  20. #include <range/v3/view/take.hpp>
  21. #include <range/v3/view/take_exactly.hpp>
  22. #include "../simple_test.hpp"
  23. #include "../test_utils.hpp"
  24. namespace
  25. {
  26. template<typename S, typename T, typename = void>
  27. struct can_convert_to : std::false_type
  28. {};
  29. template<typename S, typename T>
  30. struct can_convert_to<
  31. S, T, meta::void_<decltype(ranges::polymorphic_downcast<T>(std::declval<S>()))>>
  32. : std::true_type
  33. {};
  34. void test_polymorphic_downcast()
  35. {
  36. struct A
  37. {
  38. virtual ~A() = default;
  39. };
  40. struct B : A
  41. {};
  42. struct unrelated
  43. {};
  44. struct incomplete;
  45. CPP_assert(can_convert_to<B *, void *>());
  46. CPP_assert(can_convert_to<A *, void *>());
  47. CPP_assert(can_convert_to<B *, A *>());
  48. CPP_assert(can_convert_to<A *, B *>());
  49. CPP_assert(!can_convert_to<int, int>());
  50. CPP_assert(!can_convert_to<A const *, A *>());
  51. CPP_assert(!can_convert_to<A *, unrelated *>());
  52. CPP_assert(!can_convert_to<unrelated *, A *>());
  53. CPP_assert(!can_convert_to<incomplete *, incomplete *>());
  54. CPP_assert(can_convert_to<B &, A &>());
  55. CPP_assert(can_convert_to<A &, B &>());
  56. CPP_assert(!can_convert_to<A &, unrelated &>());
  57. CPP_assert(!can_convert_to<unrelated &, A &>());
  58. CPP_assert(!can_convert_to<incomplete &, incomplete &>());
  59. #if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4
  60. CPP_assert(can_convert_to<B &&, A &&>());
  61. CPP_assert(can_convert_to<B &, A &&>());
  62. #endif // old GCC dynamic_cast bug
  63. CPP_assert(!can_convert_to<B &&, A &>());
  64. CPP_assert(can_convert_to<A &&, B &&>());
  65. CPP_assert(!can_convert_to<A &&, B &>());
  66. CPP_assert(can_convert_to<A &, B &&>());
  67. CPP_assert(!can_convert_to<A &&, unrelated &&>());
  68. CPP_assert(!can_convert_to<A &&, unrelated &>());
  69. CPP_assert(!can_convert_to<A &, unrelated &&>());
  70. CPP_assert(!can_convert_to<unrelated &&, A &&>());
  71. CPP_assert(!can_convert_to<unrelated &&, A &>());
  72. CPP_assert(!can_convert_to<unrelated &, A &&>());
  73. CPP_assert(!can_convert_to<incomplete &&, incomplete &&>());
  74. CPP_assert(!can_convert_to<incomplete &&, incomplete &>());
  75. CPP_assert(!can_convert_to<incomplete &, incomplete &&>());
  76. }
  77. } // unnamed namespace
  78. int main()
  79. {
  80. using namespace ranges;
  81. auto const ten_ints = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  82. {
  83. any_view<int> ints = views::ints;
  84. CPP_assert(input_range<decltype(ints)> && view_<decltype(ints)>);
  85. CPP_assert(!(forward_range<decltype(ints)> && view_<decltype(ints)>));
  86. ::check_equal(std::move(ints) | views::take(10), ten_ints);
  87. }
  88. {
  89. any_view<int> ints = views::ints | views::take_exactly(5);
  90. CPP_assert(input_range<decltype(ints)> && view_<decltype(ints)>);
  91. CPP_assert(!(random_access_range<decltype(ints)> && view_<decltype(ints)>));
  92. CPP_assert(!(sized_range<decltype(ints)> && view_<decltype(ints)>));
  93. static_assert((get_categories<decltype(ints)>() & category::random_access) ==
  94. category::input,
  95. "");
  96. static_assert(
  97. (get_categories<decltype(ints)>() & category::sized) == category::none, "");
  98. }
  99. {
  100. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  101. #if defined(__clang__) && __clang_major__ < 6
  102. // Workaround https://bugs.llvm.org/show_bug.cgi?id=33314
  103. RANGES_DIAGNOSTIC_PUSH
  104. RANGES_DIAGNOSTIC_IGNORE_UNDEFINED_FUNC_TEMPLATE
  105. #endif
  106. any_view ints = views::ints | views::take_exactly(5);
  107. #if defined(__clang__) && __clang_major__ < 6
  108. RANGES_DIAGNOSTIC_POP
  109. #endif
  110. #else
  111. any_view<int, category::random_access | category::sized> ints =
  112. views::ints | views::take_exactly(5);
  113. #endif
  114. CPP_assert(random_access_range<decltype(ints)> && view_<decltype(ints)>);
  115. CPP_assert(sized_range<decltype(ints)> && view_<decltype(ints)>);
  116. static_assert((get_categories<decltype(ints)>() & category::random_access) ==
  117. category::random_access,
  118. "");
  119. static_assert(
  120. (get_categories<decltype(ints)>() & category::sized) == category::sized, "");
  121. }
  122. {
  123. any_view<int, category::input | category::sized> ints =
  124. views::ints | views::take_exactly(10);
  125. CPP_assert(input_range<decltype(ints)> && view_<decltype(ints)>);
  126. CPP_assert(sized_range<decltype(ints)> && view_<decltype(ints)>);
  127. static_assert(
  128. (get_categories<decltype(ints)>() & category::input) == category::input, "");
  129. static_assert(
  130. (get_categories<decltype(ints)>() & category::sized) == category::sized, "");
  131. }
  132. {
  133. any_view<int, category::bidirectional> ints = views::ints;
  134. CPP_assert(bidirectional_range<decltype(ints)> && view_<decltype(ints)>);
  135. CPP_assert(!(random_access_range<decltype(ints)> && view_<decltype(ints)>));
  136. static_assert((get_categories<decltype(ints)>() & category::random_access) ==
  137. category::bidirectional,
  138. "");
  139. }
  140. {
  141. any_view<int> ints2 = views::ints | views::take(10);
  142. ::check_equal(ints2, ten_ints);
  143. ::check_equal(ints2, ten_ints);
  144. }
  145. {
  146. any_view<int, category::random_access> ints3 = views::ints | views::take(10);
  147. CPP_assert(view_<decltype(ints3)>);
  148. CPP_assert(random_access_range<decltype(ints3)>);
  149. CPP_assert(!common_range<decltype(ints3)>);
  150. ::check_equal(ints3, ten_ints);
  151. ::check_equal(ints3, ten_ints);
  152. ::check_equal(aux::copy(ints3), ten_ints);
  153. ::check_equal(ints3 | views::reverse, {9, 8, 7, 6, 5, 4, 3, 2, 1, 0});
  154. }
  155. {
  156. any_view<int&> e;
  157. CHECK(e.begin() == e.begin());
  158. CHECK(e.begin() == e.end());
  159. }
  160. {
  161. iterator_t<any_view<int&, category::random_access>> i{},j{};
  162. sentinel_t<any_view<int&, category::random_access>> k{};
  163. CHECK(i == j);
  164. CHECK(i == k);
  165. CHECK((i - j) == 0);
  166. }
  167. // Regression test for #446
  168. {
  169. auto vec = std::vector<short>{begin(ten_ints), end(ten_ints)};
  170. ::check_equal(any_view<int>{vec}, ten_ints);
  171. ::check_equal(any_view<int>{ranges::detail::as_const(vec)}, ten_ints);
  172. struct Int
  173. {
  174. int i_;
  175. Int(int i) : i_{i} {}
  176. operator int() const { return i_; }
  177. };
  178. auto vec2 = std::vector<Int>{begin(ten_ints), end(ten_ints)};
  179. ::check_equal(any_view<int>{vec2}, ten_ints);
  180. }
  181. {
  182. auto v = any_view<int>{debug_input_view<int const>{
  183. ten_ints.begin(), std::ptrdiff_t(ten_ints.size())
  184. }};
  185. ::check_equal(v, ten_ints);
  186. }
  187. // Regression test for #880
  188. {
  189. using namespace ranges;
  190. std::map<int, int> mm{ {0, 1}, {2, 3} };
  191. any_view<int, category::forward | category::sized> as_any =
  192. mm | views::keys;
  193. (void)as_any;
  194. }
  195. // Regression test for #1101
  196. {
  197. using namespace ranges;
  198. std::vector<int> v = { 1, 2, 3, 4, 5 };
  199. using SizedAnyView =
  200. any_view<int, category::random_access | category::sized>;
  201. SizedAnyView av1 = v;
  202. SizedAnyView av2 = av1 | views::transform( [](auto){ return 0; } ); // fail
  203. SizedAnyView av3 = av1 | views::tail; // fail
  204. }
  205. test_polymorphic_downcast();
  206. return test_result();
  207. }