basic_iterator.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601
  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 <cstring>
  12. #include <tuple>
  13. #include <range/v3/iterator/basic_iterator.hpp>
  14. #include <range/v3/utility/common_tuple.hpp>
  15. #include "../simple_test.hpp"
  16. #include "../test_utils.hpp"
  17. template<typename T>
  18. using iter_cat_t = typename T::iterator_category;
  19. template<typename T>
  20. using has_iter_cat = meta::is_trait<meta::defer<iter_cat_t, T>>;
  21. namespace test_weak_input
  22. {
  23. template<typename I>
  24. struct cursor
  25. {
  26. I it_;
  27. struct mixin : ranges::basic_mixin<cursor>
  28. {
  29. mixin() = default;
  30. //using ranges::basic_mixin<cursor>::basic_mixin;
  31. explicit mixin(cursor && cur)
  32. : ranges::basic_mixin<cursor>(static_cast<cursor &&>(cur))
  33. {}
  34. explicit mixin(cursor const & cur)
  35. : ranges::basic_mixin<cursor>(cur)
  36. {}
  37. mixin(I i)
  38. : mixin(cursor{i})
  39. {}
  40. };
  41. cursor() = default;
  42. explicit cursor(I i)
  43. : it_(i)
  44. {}
  45. CPP_template(class J)(
  46. /// \pre
  47. requires ranges::convertible_to<J, I>) //
  48. cursor(cursor<J> that)
  49. : it_(std::move(that.it_))
  50. {}
  51. auto read() const -> decltype(*it_)
  52. {
  53. return *it_;
  54. }
  55. void next()
  56. {
  57. ++it_;
  58. }
  59. };
  60. CPP_assert(ranges::detail::input_cursor<cursor<char *>>);
  61. CPP_assert(!ranges::detail::sentinel_for_cursor<cursor<char *>, cursor<char *>>);
  62. template<class I>
  63. using iterator = ranges::basic_iterator<cursor<I>>;
  64. CPP_assert(ranges::indirectly_readable<iterator<char *>>);
  65. CPP_assert(ranges::input_iterator<iterator<char *>>);
  66. static_assert(!has_iter_cat<iterator<char *>>::value, "");
  67. static_assert(!has_iter_cat<std::iterator_traits<iterator<char *>>>::value, "");
  68. static_assert(
  69. std::is_same<iterator<char *>::iterator_concept, std::input_iterator_tag>::value,
  70. "");
  71. static_assert(!ranges::equality_comparable<iterator<char *>>, "");
  72. void test()
  73. {
  74. using namespace ranges;
  75. using I = iterator<char const *>;
  76. CPP_assert(std::is_same<std::iterator_traits<I>::pointer, char const *>{});
  77. static char const sz[] = "hello world";
  78. I i{sz};
  79. CHECK(*i == 'h');
  80. CHECK(&*i == i.operator->());
  81. ++i;
  82. CHECK(*i == 'e');
  83. CHECK(&*i == i.operator->());
  84. }
  85. } // namespace test_weak_input
  86. namespace test_random_access
  87. {
  88. template<typename I>
  89. struct cursor
  90. {
  91. I it_;
  92. struct mixin : ranges::basic_mixin<cursor>
  93. {
  94. mixin() = default;
  95. //using ranges::basic_mixin<cursor>::basic_mixin;
  96. explicit mixin(cursor && cur)
  97. : ranges::basic_mixin<cursor>(static_cast<cursor &&>(cur))
  98. {}
  99. explicit mixin(cursor const & cur)
  100. : ranges::basic_mixin<cursor>(cur)
  101. {}
  102. mixin(I i)
  103. : mixin(cursor{i})
  104. {}
  105. };
  106. cursor() = default;
  107. explicit cursor(I i)
  108. : it_(i)
  109. {}
  110. CPP_template(class J)(
  111. /// \pre
  112. requires ranges::convertible_to<J, I>) //
  113. cursor(cursor<J> that)
  114. : it_(std::move(that.it_))
  115. {}
  116. auto read() const -> decltype(*it_)
  117. {
  118. return *it_;
  119. }
  120. CPP_template(class J)(
  121. /// \pre
  122. requires ranges::sentinel_for<J, I>) //
  123. bool equal(cursor<J> const & that) const
  124. {
  125. return that.it_ == it_;
  126. }
  127. void next()
  128. {
  129. ++it_;
  130. }
  131. void prev()
  132. {
  133. --it_;
  134. }
  135. void advance(ranges::iter_difference_t<I> n)
  136. {
  137. it_ += n;
  138. }
  139. CPP_template(class J)(
  140. /// \pre
  141. requires ranges::sized_sentinel_for<J, I>) //
  142. ranges::iter_difference_t<I> distance_to(cursor<J> const & that) const
  143. {
  144. return that.it_ - it_;
  145. }
  146. };
  147. CPP_assert(ranges::detail::random_access_cursor<cursor<char *>>);
  148. template<class I>
  149. using iterator = ranges::basic_iterator<cursor<I>>;
  150. static_assert(std::is_same<iterator<char *>::iterator_category,
  151. std::random_access_iterator_tag>::value,
  152. "");
  153. void test()
  154. {
  155. using namespace ranges;
  156. iterator<char *> a(nullptr);
  157. iterator<char const *> b(nullptr);
  158. iterator<char const *> c(a);
  159. CPP_assert(
  160. std::is_same<std::iterator_traits<iterator<char *>>::pointer, char *>{});
  161. b = a;
  162. bool d = a == b;
  163. d = (a != b);
  164. detail::ignore_unused(
  165. d, //
  166. a < b, //
  167. a <= b, //
  168. a > b, //
  169. a >= b, //
  170. (a-b), //
  171. (b-a), //
  172. (a-a), //
  173. (b-b)); //
  174. }
  175. } // namespace test_random_access
  176. namespace test_weak_output
  177. {
  178. template<typename I>
  179. struct cursor
  180. {
  181. struct mixin : ranges::basic_mixin<cursor>
  182. {
  183. mixin() = default;
  184. // using ranges::basic_mixin<cursor>::basic_mixin;
  185. explicit mixin(cursor && cur)
  186. : ranges::basic_mixin<cursor>(static_cast<cursor &&>(cur))
  187. {}
  188. explicit mixin(cursor const & cur)
  189. : ranges::basic_mixin<cursor>(cur)
  190. {}
  191. explicit mixin(I i)
  192. : mixin(cursor{i})
  193. {}
  194. };
  195. cursor() = default;
  196. explicit cursor(I i)
  197. : it_(i)
  198. {}
  199. void write(ranges::iter_value_t<I> v) const
  200. {
  201. *it_ = v;
  202. }
  203. void next()
  204. {
  205. ++it_;
  206. }
  207. private:
  208. I it_;
  209. };
  210. CPP_assert(ranges::detail::output_cursor<cursor<char *>, char>);
  211. CPP_assert(!ranges::detail::sentinel_for_cursor<cursor<char *>, cursor<char *>>);
  212. template<class I>
  213. using iterator = ranges::basic_iterator<cursor<I>>;
  214. CPP_assert(ranges::output_iterator<iterator<char *>, char>);
  215. CPP_assert(!ranges::equality_comparable<iterator<char *>>);
  216. void test()
  217. {
  218. char buf[10];
  219. iterator<char *> i(buf);
  220. *i = 'h';
  221. ++i;
  222. *i = 'e';
  223. ++i;
  224. *i = 'l';
  225. ++i;
  226. *i = 'l';
  227. ++i;
  228. *i = 'o';
  229. ++i;
  230. *i = '\0';
  231. CHECK(0 == std::strcmp(buf, "hello"));
  232. }
  233. } // namespace test_weak_output
  234. namespace test_output
  235. {
  236. template<typename I>
  237. struct cursor
  238. {
  239. I it_;
  240. struct mixin : ranges::basic_mixin<cursor>
  241. {
  242. mixin() = default;
  243. //using ranges::basic_mixin<cursor>::basic_mixin;
  244. explicit mixin(cursor && cur)
  245. : ranges::basic_mixin<cursor>(static_cast<cursor &&>(cur))
  246. {}
  247. explicit mixin(cursor const & cur)
  248. : ranges::basic_mixin<cursor>(cur)
  249. {}
  250. mixin(I i)
  251. : mixin(cursor{i})
  252. {}
  253. };
  254. cursor() = default;
  255. explicit cursor(I i)
  256. : it_(i)
  257. {}
  258. CPP_template(class J)(
  259. /// \pre
  260. requires ranges::convertible_to<J, I>) //
  261. cursor(cursor<J> that)
  262. : it_(std::move(that.it_))
  263. {}
  264. using value_type = ranges::iter_value_t<I>;
  265. value_type read() const
  266. {
  267. return *it_;
  268. }
  269. void write(value_type v) const
  270. {
  271. *it_ = v;
  272. }
  273. I arrow() const
  274. {
  275. return it_;
  276. }
  277. void next()
  278. {
  279. ++it_;
  280. }
  281. bool equal(cursor const & that) const
  282. {
  283. return it_ == that.it_;
  284. }
  285. };
  286. CPP_assert(ranges::detail::output_cursor<cursor<char *>, char>);
  287. CPP_assert(ranges::detail::forward_cursor<cursor<char *>>);
  288. template<class I>
  289. using iterator = ranges::basic_iterator<cursor<I>>;
  290. CPP_assert(ranges::output_iterator<iterator<char *>, char>);
  291. CPP_assert(ranges::forward_iterator<iterator<char *>>);
  292. CPP_assert(std::is_same<std::iterator_traits<iterator<char *>>::pointer, char *>());
  293. void test()
  294. {
  295. char buf[10];
  296. iterator<char *> i(buf);
  297. *i = 'h';
  298. CHECK(*i == 'h');
  299. CHECK(*i == *i);
  300. ++i;
  301. *i = 'e';
  302. CHECK('e' == *i);
  303. ++i;
  304. *i = 'l';
  305. ++i;
  306. *i = 'l';
  307. ++i;
  308. *i = 'o';
  309. ++i;
  310. *i = '\0';
  311. CHECK(0 == std::strcmp(buf, "hello"));
  312. CHECK(i == iterator<char *>{buf + 5});
  313. ++i;
  314. CHECK(i != iterator<char *>{buf + 5});
  315. CHECK(i == iterator<char *>{buf + 6});
  316. }
  317. } // namespace test_output
  318. namespace test_move_only
  319. {
  320. struct MoveOnly
  321. {
  322. MoveOnly() = default;
  323. MoveOnly(MoveOnly &&) = default;
  324. MoveOnly(MoveOnly const &) = delete;
  325. MoveOnly & operator=(MoveOnly &&) = default;
  326. MoveOnly & operator=(MoveOnly const &) = delete;
  327. };
  328. template<typename I>
  329. struct zip1_cursor
  330. {
  331. I it_;
  332. struct mixin : ranges::basic_mixin<zip1_cursor>
  333. {
  334. mixin() = default;
  335. // using ranges::basic_mixin<zip1_cursor>::basic_mixin;
  336. explicit mixin(zip1_cursor && cur)
  337. : ranges::basic_mixin<zip1_cursor>(static_cast<zip1_cursor &&>(cur))
  338. {}
  339. explicit mixin(zip1_cursor const & cur)
  340. : ranges::basic_mixin<zip1_cursor>(cur)
  341. {}
  342. mixin(I i)
  343. : mixin(zip1_cursor{i})
  344. {}
  345. };
  346. zip1_cursor() = default;
  347. explicit zip1_cursor(I i)
  348. : it_(i)
  349. {}
  350. CPP_template(class J)(
  351. /// \pre
  352. requires ranges::convertible_to<J, I>) //
  353. zip1_cursor(zip1_cursor<J> that)
  354. : it_(std::move(that.it_))
  355. {}
  356. using value_type = std::tuple<ranges::iter_value_t<I>>;
  357. using reference = ranges::common_tuple<ranges::iter_reference_t<I>>;
  358. using rvalue_reference = ranges::common_tuple<ranges::iter_rvalue_reference_t<I>>;
  359. reference read() const
  360. {
  361. return reference{*it_};
  362. }
  363. rvalue_reference move() const
  364. {
  365. return rvalue_reference{ranges::iter_move(it_)};
  366. }
  367. void write(reference const & v) const
  368. {
  369. reference{ *it_} = v;
  370. }
  371. void write(value_type && v) const
  372. {
  373. reference{ *it_} = std::move(v);
  374. }
  375. void next()
  376. {
  377. ++it_;
  378. }
  379. bool equal(zip1_cursor const & that) const
  380. {
  381. return it_ == that.it_;
  382. }
  383. };
  384. CPP_assert(
  385. ranges::detail::output_cursor<zip1_cursor<MoveOnly *>, std::tuple<MoveOnly>
  386. &&>);
  387. CPP_assert(ranges::detail::forward_cursor<zip1_cursor<MoveOnly *>>);
  388. template<class I>
  389. using iterator = ranges::basic_iterator<zip1_cursor<I>>;
  390. CPP_assert(ranges::output_iterator<iterator<MoveOnly *>, std::tuple<MoveOnly> &&>);
  391. CPP_assert(ranges::forward_iterator<iterator<MoveOnly *>>);
  392. void test()
  393. {
  394. MoveOnly buf[10] = {};
  395. iterator<MoveOnly *> i(buf);
  396. *i = std::tuple<MoveOnly>{};
  397. ranges::common_tuple<MoveOnly &> x = *i;
  398. (void)x;
  399. std::tuple<MoveOnly> v = ranges::iter_move(i);
  400. *i = std::move(v);
  401. }
  402. } // namespace test_move_only
  403. namespace test_forward_sized
  404. {
  405. template<typename I>
  406. struct cursor
  407. {
  408. I it_;
  409. struct mixin : ranges::basic_mixin<cursor>
  410. {
  411. mixin() = default;
  412. // using ranges::basic_mixin<cursor>::basic_mixin;
  413. explicit mixin(cursor && cur)
  414. : ranges::basic_mixin<cursor>(static_cast<cursor &&>(cur))
  415. {}
  416. explicit mixin(cursor const & cur)
  417. : ranges::basic_mixin<cursor>(cur)
  418. {}
  419. mixin(I i)
  420. : mixin(cursor{i})
  421. {}
  422. };
  423. cursor() = default;
  424. explicit cursor(I i)
  425. : it_(i)
  426. {}
  427. CPP_template(class J)(
  428. /// \pre
  429. requires ranges::convertible_to<J, I>) //
  430. cursor(cursor<J> that)
  431. : it_(std::move(that.it_))
  432. {}
  433. auto read() const -> decltype(*it_)
  434. {
  435. return *it_;
  436. }
  437. CPP_template(class J)(
  438. /// \pre
  439. requires ranges::sentinel_for<J, I>) //
  440. bool equal(cursor<J> const & that) const
  441. {
  442. return that.it_ == it_;
  443. }
  444. void next()
  445. {
  446. ++it_;
  447. }
  448. CPP_template(class J)(
  449. /// \pre
  450. requires ranges::sized_sentinel_for<J, I>) //
  451. ranges::iter_difference_t<I> distance_to(cursor<J> const & that) const
  452. {
  453. return that.it_ - it_;
  454. }
  455. };
  456. CPP_assert(ranges::detail::sized_sentinel_for_cursor<cursor<char *>, cursor<char *>>);
  457. CPP_assert(ranges::detail::forward_cursor<cursor<char *>>);
  458. template<class I>
  459. using iterator = ranges::basic_iterator<cursor<I>>;
  460. static_assert(std::is_same<iterator<char *>::iterator_category,
  461. std::forward_iterator_tag>::value,
  462. "");
  463. void test()
  464. {
  465. using namespace ranges;
  466. iterator<char *> a(nullptr);
  467. iterator<char const *> b(nullptr);
  468. iterator<char const *> c(a);
  469. b = a;
  470. bool d = a == b;
  471. d = (a != b);
  472. detail::ignore_unused(
  473. d, //
  474. a < b, //
  475. a <= b, //
  476. a > b, //
  477. a >= b, //
  478. (a-b), //
  479. (b-a), //
  480. (a-a), //
  481. (b-b)); //
  482. }
  483. } // namespace test_forward_sized
  484. RANGES_DIAGNOSTIC_IGNORE_UNNEEDED_MEMBER
  485. void test_box()
  486. {
  487. struct A : ranges::box<int>
  488. {};
  489. CHECK(sizeof(A) == sizeof(int));
  490. struct empty
  491. {};
  492. struct B : ranges::box<empty>
  493. {
  494. int i;
  495. };
  496. CHECK(sizeof(B) == sizeof(int));
  497. B b1, b2;
  498. if(ranges::detail::box_compression<empty>() == ranges::detail::box_compress::coalesce)
  499. CHECK((&b1.get() == &b2.get()));
  500. struct nontrivial
  501. {
  502. nontrivial()
  503. {}
  504. };
  505. struct C : ranges::box<nontrivial>
  506. {
  507. int i;
  508. };
  509. CHECK(sizeof(C) == sizeof(int));
  510. C c1, c2;
  511. CHECK((&c1.get() != &c2.get()));
  512. {
  513. // empty but not trivial cursor that defines value_type:
  514. struct cursor
  515. {
  516. using value_type = int;
  517. cursor()
  518. {}
  519. int read() const
  520. {
  521. return 42;
  522. }
  523. void next()
  524. {}
  525. };
  526. CPP_assert(ranges::detail::box_compression<cursor>() ==
  527. ranges::detail::box_compress::ebo);
  528. CPP_assert(ranges::same_as<int, ranges::basic_iterator<cursor>::value_type>);
  529. }
  530. }
  531. int main()
  532. {
  533. using namespace ranges;
  534. std::cout << "\nTesting basic_iterator\n";
  535. ::test_weak_input::test();
  536. ::test_random_access::test();
  537. ::test_weak_output::test();
  538. ::test_output::test();
  539. ::test_move_only::test();
  540. ::test_forward_sized::test();
  541. ::test_box();
  542. return ::test_result();
  543. }