iterator.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445
  1. // Range v3 library
  2. //
  3. // Copyright Eric Niebler 2014, 2016
  4. // Copyright Casey Carter 2016
  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. #include <list>
  13. #include <ostream>
  14. #include <sstream>
  15. #include <string>
  16. #include <vector>
  17. #include <meta/meta.hpp>
  18. #include <range/v3/iterator/operations.hpp>
  19. #include <range/v3/iterator/move_iterators.hpp>
  20. #include <range/v3/iterator/insert_iterators.hpp>
  21. #include <range/v3/iterator/stream_iterators.hpp>
  22. #include <range/v3/algorithm/copy.hpp>
  23. #include "../simple_test.hpp"
  24. #include "../test_utils.hpp"
  25. using namespace ranges;
  26. struct MoveOnlyReadable
  27. {
  28. using value_type = std::unique_ptr<int>;
  29. value_type operator*() const;
  30. };
  31. CPP_assert(indirectly_readable<MoveOnlyReadable>);
  32. void test_insert_iterator()
  33. {
  34. CPP_assert(output_iterator<insert_iterator<std::vector<int>>, int&&>);
  35. CPP_assert(!equality_comparable<insert_iterator<std::vector<int>>>);
  36. std::vector<int> vi{5,6,7,8};
  37. copy(std::initializer_list<int>{1,2,3,4}, inserter(vi, vi.begin()+2));
  38. ::check_equal(vi, {5,6,1,2,3,4,7,8});
  39. }
  40. void test_ostream_joiner()
  41. {
  42. std::ostringstream oss;
  43. std::vector<int> vi{};
  44. copy(vi, make_ostream_joiner(oss, ","));
  45. ::check_equal(oss.str(), std::string{""});
  46. vi = {1,2,3,4};
  47. copy(vi, make_ostream_joiner(oss, ","));
  48. ::check_equal(oss.str(), std::string{"1,2,3,4"});
  49. }
  50. void test_move_iterator()
  51. {
  52. std::vector<MoveOnlyString> in;
  53. in.emplace_back("this");
  54. in.emplace_back("is");
  55. in.emplace_back("his");
  56. in.emplace_back("face");
  57. std::vector<MoveOnlyString> out;
  58. auto first = ranges::make_move_iterator(in.begin());
  59. using I = decltype(first);
  60. CPP_assert(input_iterator<I>);
  61. CPP_assert(!forward_iterator<I>);
  62. CPP_assert(same_as<I, ranges::move_iterator<std::vector<MoveOnlyString>::iterator>>);
  63. auto last = ranges::make_move_sentinel(in.end());
  64. using S = decltype(last);
  65. CPP_assert(sentinel_for<S, I>);
  66. CPP_assert(sized_sentinel_for<I, I>);
  67. CHECK((first - first) == 0);
  68. CPP_assert(sized_sentinel_for<S, I>);
  69. CHECK(static_cast<std::size_t>(last - first) == in.size());
  70. ranges::copy(first, last, ranges::back_inserter(out));
  71. ::check_equal(in, {"","","",""});
  72. ::check_equal(out, {"this","is","his","face"});
  73. }
  74. template<class I>
  75. using RI = std::reverse_iterator<I>;
  76. void issue_420_regression()
  77. {
  78. // Verify that sized_sentinel_for<std::reverse_iterator<S>, std::reverse_iterator<I>>
  79. // properly requires sized_sentinel_for<I, S>
  80. CPP_assert(sized_sentinel_for<RI<int*>, RI<int*>>);
  81. CPP_assert(!sized_sentinel_for<RI<int*>, RI<float*>>);
  82. using BI = BidirectionalIterator<int*>;
  83. CPP_assert(!sized_sentinel_for<RI<BI>, RI<BI>>);
  84. }
  85. struct value_type_tester_thingy {};
  86. namespace ranges
  87. {
  88. template<>
  89. struct indirectly_readable_traits<::value_type_tester_thingy>
  90. {
  91. using value_type = int;
  92. };
  93. }
  94. template<typename T>
  95. struct with_value_type { using value_type = T; };
  96. template<typename T>
  97. struct with_element_type { using element_type = T; };
  98. // arrays of known bound
  99. CPP_assert(same_as<int, ranges::indirectly_readable_traits<int[4]>::value_type>);
  100. CPP_assert(same_as<int, ranges::indirectly_readable_traits<const int[4]>::value_type>);
  101. CPP_assert(same_as<int*, ranges::indirectly_readable_traits<int*[4]>::value_type>);
  102. CPP_assert(same_as<with_value_type<int>, ranges::indirectly_readable_traits<with_value_type<int>[4]>::value_type>);
  103. #if !defined(__GNUC__) || defined(__clang__)
  104. // arrays of unknown bound
  105. CPP_assert(same_as<int, ranges::indirectly_readable_traits<int[]>::value_type>);
  106. CPP_assert(same_as<int, ranges::indirectly_readable_traits<const int[]>::value_type>);
  107. #endif
  108. template<typename T>
  109. using readable_traits_value_type_t = typename ranges::indirectly_readable_traits<T>::value_type;
  110. template<typename T>
  111. using readable_traits_value_type = meta::defer<readable_traits_value_type_t, T>;
  112. // object pointer types
  113. CPP_assert(same_as<int, ranges::indirectly_readable_traits<int*>::value_type>);
  114. CPP_assert(same_as<int, ranges::indirectly_readable_traits<int*const>::value_type>);
  115. CPP_assert(same_as<int, ranges::indirectly_readable_traits<int const*>::value_type>);
  116. CPP_assert(same_as<int, ranges::indirectly_readable_traits<int const*const>::value_type>);
  117. CPP_assert(same_as<int[4], ranges::indirectly_readable_traits<int(*)[4]>::value_type>);
  118. CPP_assert(same_as<int[4], ranges::indirectly_readable_traits<const int(*)[4]>::value_type>);
  119. struct incomplete;
  120. CPP_assert(same_as<incomplete, ranges::indirectly_readable_traits<incomplete*>::value_type>);
  121. static_assert(!meta::is_trait<readable_traits_value_type<void*>>::value, "");
  122. static_assert(!meta::is_trait<readable_traits_value_type<void const*>>::value, "");
  123. // class types with member value_type
  124. CPP_assert(same_as<int, ranges::indirectly_readable_traits<with_value_type<int>>::value_type>);
  125. CPP_assert(same_as<int, ranges::indirectly_readable_traits<with_value_type<int> const>::value_type>);
  126. CPP_assert(same_as<int, ranges::indirectly_readable_traits<value_type_tester_thingy>::value_type>);
  127. CPP_assert(same_as<int, ranges::indirectly_readable_traits<value_type_tester_thingy const>::value_type>);
  128. CPP_assert(same_as<int[4], ranges::indirectly_readable_traits<with_value_type<int[4]>>::value_type>);
  129. CPP_assert(same_as<int[4], ranges::indirectly_readable_traits<with_value_type<int[4]> const>::value_type>);
  130. static_assert(!meta::is_trait<readable_traits_value_type<with_value_type<void>>>::value, "");
  131. static_assert(!meta::is_trait<readable_traits_value_type<with_value_type<int(int)>>>::value, "");
  132. static_assert(!meta::is_trait<readable_traits_value_type<with_value_type<int&>>>::value, "");
  133. // class types with member element_type
  134. CPP_assert(same_as<int, ranges::indirectly_readable_traits<with_element_type<int>>::value_type>);
  135. CPP_assert(same_as<int, ranges::indirectly_readable_traits<with_element_type<int> const>::value_type>);
  136. CPP_assert(same_as<int, ranges::indirectly_readable_traits<with_element_type<int const>>::value_type>);
  137. CPP_assert(same_as<int[4], ranges::indirectly_readable_traits<with_element_type<int[4]>>::value_type>);
  138. CPP_assert(same_as<int[4], ranges::indirectly_readable_traits<with_element_type<int[4]> const>::value_type>);
  139. CPP_assert(same_as<int[4], ranges::indirectly_readable_traits<with_element_type<int const[4]>>::value_type>);
  140. static_assert(!meta::is_trait<readable_traits_value_type<with_element_type<void>>>::value, "");
  141. static_assert(!meta::is_trait<readable_traits_value_type<with_element_type<void const>>>::value, "");
  142. static_assert(!meta::is_trait<readable_traits_value_type<with_element_type<void> const>>::value, "");
  143. static_assert(!meta::is_trait<readable_traits_value_type<with_element_type<int(int)>>>::value, "");
  144. static_assert(!meta::is_trait<readable_traits_value_type<with_element_type<int&>>>::value, "");
  145. // cv-void
  146. static_assert(!meta::is_trait<readable_traits_value_type<void>>::value, "");
  147. static_assert(!meta::is_trait<readable_traits_value_type<void const>>::value, "");
  148. // reference types
  149. static_assert(!meta::is_trait<readable_traits_value_type<int&>>::value, "");
  150. static_assert(!meta::is_trait<readable_traits_value_type<int&&>>::value, "");
  151. static_assert(!meta::is_trait<readable_traits_value_type<int*&>>::value, "");
  152. static_assert(!meta::is_trait<readable_traits_value_type<int*&&>>::value, "");
  153. static_assert(!meta::is_trait<readable_traits_value_type<int(&)(int)>>::value, "");
  154. static_assert(!meta::is_trait<readable_traits_value_type<std::ostream&>>::value, "");
  155. CPP_assert(indirectly_swappable<int *, int *>);
  156. CPP_assert(indirectly_movable<int const *, int *>);
  157. CPP_assert(!indirectly_swappable<int const *, int const *>);
  158. CPP_assert(!indirectly_movable<int const *, int const *>);
  159. namespace Boost
  160. {
  161. struct S {}; // just to have a type from Boost namespace
  162. template<typename I, typename D>
  163. void advance(I&, D)
  164. {}
  165. }
  166. // Regression test for https://github.com/ericniebler/range-v3/issues/845
  167. void test_845()
  168. {
  169. std::list<std::pair<Boost::S, int>> v = { {Boost::S{}, 0} };
  170. auto itr = v.begin();
  171. ranges::advance(itr, 1); // Should not create ambiguity
  172. }
  173. // Test for https://github.com/ericniebler/range-v3/issues/1110
  174. void test_1110()
  175. {
  176. // this should not trigger assertation error
  177. std::vector<int> v = {1,2,3};
  178. auto e = ranges::end(v);
  179. ranges::advance(e, 0, ranges::begin(v));
  180. }
  181. // Test the deep integration with the STL
  182. #if defined(RANGES_DEEP_STL_INTEGRATION) && RANGES_DEEP_STL_INTEGRATION
  183. struct X
  184. {
  185. int& operator*() const;
  186. X & operator++();
  187. struct proxy { operator int() const; };
  188. proxy operator++(int);
  189. };
  190. namespace std
  191. {
  192. template <>
  193. struct iterator_traits<::X>
  194. {
  195. using value_type = int;
  196. using reference = int&;
  197. using pointer = int*;
  198. using difference_type = ptrdiff_t;
  199. using iterator_category = std::input_iterator_tag;
  200. };
  201. }
  202. static_assert(ranges::input_iterator<X>, "");
  203. struct Y
  204. {
  205. using value_type = int;
  206. using difference_type = std::ptrdiff_t;
  207. using iterator_category = std::bidirectional_iterator_tag;
  208. using reference = int&;
  209. using pointer = int*;
  210. int& operator*() const noexcept;
  211. };
  212. static_assert(std::is_same<std::add_pointer_t<int&>, int*>::value, "");
  213. struct Z
  214. {
  215. using difference_type = std::ptrdiff_t;
  216. using iterator_category = std::bidirectional_iterator_tag;
  217. int& operator*() const noexcept;
  218. Z& operator++();
  219. Z operator++(int);
  220. bool operator==(Z) const;
  221. bool operator!=(Z) const;
  222. };
  223. namespace ranges
  224. {
  225. template <>
  226. struct indirectly_readable_traits<::Z>
  227. {
  228. using value_type = int;
  229. };
  230. }
  231. // Looks like an STL2 forward iterator, but the conformance beyond
  232. // input is "accidental".
  233. struct WouldBeFwd
  234. {
  235. using value_type = struct S{ };
  236. using difference_type = std::ptrdiff_t;
  237. S & operator*() const;
  238. WouldBeFwd& operator++();
  239. WouldBeFwd operator++(int);
  240. //S* operator->() const;
  241. bool operator==(WouldBeFwd) const;
  242. bool operator!=(WouldBeFwd) const;
  243. };
  244. namespace std
  245. {
  246. template <>
  247. struct iterator_traits<::WouldBeFwd>
  248. {
  249. using value_type = ::WouldBeFwd::value_type;
  250. using difference_type = ::WouldBeFwd::difference_type;
  251. using reference = iter_reference_t<::WouldBeFwd>;
  252. using pointer = add_pointer_t<reference>;
  253. // Explicit opt-out of stl2's forward_iterator concept:
  254. using iterator_category = std::input_iterator_tag; // STL1-style iterator category
  255. };
  256. }
  257. // Looks like an STL2 bidirectional iterator, but the conformance beyond
  258. // forward is "accidental".
  259. struct WouldBeBidi
  260. {
  261. using value_type = struct S{ };
  262. using difference_type = std::ptrdiff_t;
  263. // using iterator_category = std::input_iterator_tag;
  264. // using iterator_concept = std::forward_iterator_tag;
  265. S operator*() const; // by value!
  266. WouldBeBidi& operator++();
  267. WouldBeBidi operator++(int);
  268. WouldBeBidi& operator--();
  269. WouldBeBidi operator--(int);
  270. //S* operator->() const;
  271. bool operator==(WouldBeBidi) const;
  272. bool operator!=(WouldBeBidi) const;
  273. };
  274. namespace std
  275. {
  276. template <>
  277. struct iterator_traits<::WouldBeBidi>
  278. {
  279. using value_type = ::WouldBeBidi::value_type;
  280. using difference_type = ::WouldBeBidi::difference_type;
  281. using reference = value_type;
  282. using pointer = value_type*;
  283. using iterator_category = std::input_iterator_tag; // STL1-style iterator category
  284. // Explicit opt-out of stl2's bidirectional_iterator concept:
  285. using iterator_concept = std::forward_iterator_tag; // STL2-style iterator category
  286. };
  287. }
  288. struct OutIter
  289. {
  290. using difference_type = std::ptrdiff_t;
  291. OutIter& operator=(int);
  292. OutIter& operator*();
  293. OutIter& operator++();
  294. OutIter& operator++(int);
  295. };
  296. // proxy iterator
  297. struct bool_iterator
  298. {
  299. using value_type = bool;
  300. struct reference
  301. {
  302. operator bool() const { return true; }
  303. reference();
  304. reference(reference const &);
  305. reference& operator=(reference);
  306. reference& operator=(bool);
  307. };
  308. using difference_type = std::ptrdiff_t;
  309. reference operator*() const;
  310. bool_iterator& operator++();
  311. bool_iterator operator++(int);
  312. bool operator==(bool_iterator) const;
  313. bool operator!=(bool_iterator) const;
  314. friend reference iter_move(bool_iterator i) { return *i; }
  315. friend void iter_swap(bool_iterator, bool_iterator) { }
  316. };
  317. void deep_integration_test()
  318. {
  319. using std::is_same;
  320. using std::iterator_traits;
  321. using ranges::iter_value_t;
  322. using ranges::iter_difference_t;
  323. static_assert(is_same<iter_difference_t<std::int_least16_t>, int>::value, "");
  324. static_assert(is_same<iter_difference_t<std::uint_least16_t>, int>::value, "");
  325. static_assert(is_same<iter_difference_t<std::int_least32_t>, std::int_least32_t>::value, "");
  326. static_assert(is_same<iter_difference_t<std::uint_least32_t>, meta::_t<std::make_signed<std::uint_least32_t>>>::value, "");
  327. static_assert(is_same<iter_difference_t<std::uint_least64_t>, meta::_t<std::make_signed<std::uint_least64_t>>>::value, "");
  328. static_assert(is_same<iter_value_t<const int*>, int>::value, "");
  329. static_assert(is_same<iter_difference_t<const int*>, ptrdiff_t>::value, "");
  330. static_assert(is_same<iter_difference_t<int* const>, ptrdiff_t>::value, "");
  331. static_assert(detail::is_std_iterator_traits_specialized_v<X>, "");
  332. static_assert(is_same<iterator_traits<X>::value_type, int>::value, "");
  333. static_assert(is_same<iter_value_t<X>, int>::value, "");
  334. static_assert(!detail::is_std_iterator_traits_specialized_v<Y>, "");
  335. static_assert(is_same<iterator_traits<Y>::value_type, int>::value, "");
  336. static_assert(is_same<iter_value_t<Y>, int>::value, "");
  337. // libc++ has a broken std::iterator_traits primary template
  338. // https://bugs.llvm.org/show_bug.cgi?id=39619
  339. #ifndef _LIBCPP_VERSION
  340. // iterator_traits uses specializations of ranges::indirectly_readable_traits:
  341. static_assert(!detail::is_std_iterator_traits_specialized_v<Z>, "");
  342. static_assert(is_same<iterator_traits<Z>::value_type, int>::value, "");
  343. static_assert(is_same<iter_value_t<Z>, int>::value, "");
  344. static_assert(is_same<iterator_traits<Z>::iterator_category,
  345. std::bidirectional_iterator_tag>::value, "");
  346. #endif
  347. static_assert(ranges::input_iterator<WouldBeFwd>, "");
  348. static_assert(!ranges::forward_iterator<WouldBeFwd>, "");
  349. static_assert(is_same<iterator_traits<WouldBeFwd>::iterator_category,
  350. std::input_iterator_tag>::value, "");
  351. static_assert(ranges::forward_iterator<WouldBeBidi>, "");
  352. static_assert(!ranges::bidirectional_iterator<WouldBeBidi>, "");
  353. static_assert(is_same<iterator_traits<WouldBeBidi>::iterator_category,
  354. std::input_iterator_tag>::value, "");
  355. static_assert(ranges::input_or_output_iterator<OutIter>, "");
  356. static_assert(!ranges::input_iterator<OutIter>, "");
  357. static_assert(is_same<iterator_traits<OutIter>::difference_type,
  358. std::ptrdiff_t>::value, "");
  359. static_assert(is_same<iterator_traits<OutIter>::iterator_category,
  360. std::output_iterator_tag>::value, "");
  361. static_assert(ranges::contiguous_iterator<int volatile *>, "");
  362. static_assert(ranges::forward_iterator<bool_iterator>, "");
  363. static_assert(is_same<iterator_traits<bool_iterator>::iterator_category,
  364. std::input_iterator_tag>::value, "");
  365. // static_assert(_Cpp98InputIterator<int volatile*>);
  366. // static_assert(_Cpp98InputIterator<bool_iterator>);
  367. // // Test subsumption:
  368. // test(WouldBeFwd{});
  369. // test(WouldBeBidi{});
  370. // test(meta::detail::nullptr_v<int>);
  371. // // Test subsumption:
  372. // test2(OutIter{});
  373. // test2(meta::detail::nullptr_v<int>);
  374. // // Test subsumption:
  375. // test3(WouldBeFwd{}, WouldBeFwd{});
  376. // test3(meta::detail::nullptr_v<int>, meta::detail::nullptr_v<int>);
  377. }
  378. #endif
  379. int main()
  380. {
  381. test_insert_iterator();
  382. test_move_iterator();
  383. test_ostream_joiner();
  384. issue_420_regression();
  385. test_1110();
  386. {
  387. struct S { using value_type = int; };
  388. CPP_assert(same_as<int, ranges::indirectly_readable_traits<S const>::value_type>);
  389. }
  390. return ::test_result();
  391. }