| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601 |
- // Range v3 library
- //
- // Copyright Eric Niebler 2014-present
- //
- // Use, modification and distribution is subject to the
- // Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- //
- // Project home: https://github.com/ericniebler/range-v3
- #include <cstring>
- #include <tuple>
- #include <range/v3/iterator/basic_iterator.hpp>
- #include <range/v3/utility/common_tuple.hpp>
- #include "../simple_test.hpp"
- #include "../test_utils.hpp"
- template<typename T>
- using iter_cat_t = typename T::iterator_category;
- template<typename T>
- using has_iter_cat = meta::is_trait<meta::defer<iter_cat_t, T>>;
- namespace test_weak_input
- {
- template<typename I>
- struct cursor
- {
- I it_;
- struct mixin : ranges::basic_mixin<cursor>
- {
- mixin() = default;
- //using ranges::basic_mixin<cursor>::basic_mixin;
- explicit mixin(cursor && cur)
- : ranges::basic_mixin<cursor>(static_cast<cursor &&>(cur))
- {}
- explicit mixin(cursor const & cur)
- : ranges::basic_mixin<cursor>(cur)
- {}
- mixin(I i)
- : mixin(cursor{i})
- {}
- };
- cursor() = default;
- explicit cursor(I i)
- : it_(i)
- {}
- CPP_template(class J)(
- /// \pre
- requires ranges::convertible_to<J, I>) //
- cursor(cursor<J> that)
- : it_(std::move(that.it_))
- {}
- auto read() const -> decltype(*it_)
- {
- return *it_;
- }
- void next()
- {
- ++it_;
- }
- };
- CPP_assert(ranges::detail::input_cursor<cursor<char *>>);
- CPP_assert(!ranges::detail::sentinel_for_cursor<cursor<char *>, cursor<char *>>);
- template<class I>
- using iterator = ranges::basic_iterator<cursor<I>>;
- CPP_assert(ranges::indirectly_readable<iterator<char *>>);
- CPP_assert(ranges::input_iterator<iterator<char *>>);
- static_assert(!has_iter_cat<iterator<char *>>::value, "");
- static_assert(!has_iter_cat<std::iterator_traits<iterator<char *>>>::value, "");
- static_assert(
- std::is_same<iterator<char *>::iterator_concept, std::input_iterator_tag>::value,
- "");
- static_assert(!ranges::equality_comparable<iterator<char *>>, "");
- void test()
- {
- using namespace ranges;
- using I = iterator<char const *>;
- CPP_assert(std::is_same<std::iterator_traits<I>::pointer, char const *>{});
- static char const sz[] = "hello world";
- I i{sz};
- CHECK(*i == 'h');
- CHECK(&*i == i.operator->());
- ++i;
- CHECK(*i == 'e');
- CHECK(&*i == i.operator->());
- }
- } // namespace test_weak_input
- namespace test_random_access
- {
- template<typename I>
- struct cursor
- {
- I it_;
- struct mixin : ranges::basic_mixin<cursor>
- {
- mixin() = default;
- //using ranges::basic_mixin<cursor>::basic_mixin;
- explicit mixin(cursor && cur)
- : ranges::basic_mixin<cursor>(static_cast<cursor &&>(cur))
- {}
- explicit mixin(cursor const & cur)
- : ranges::basic_mixin<cursor>(cur)
- {}
- mixin(I i)
- : mixin(cursor{i})
- {}
- };
- cursor() = default;
- explicit cursor(I i)
- : it_(i)
- {}
- CPP_template(class J)(
- /// \pre
- requires ranges::convertible_to<J, I>) //
- cursor(cursor<J> that)
- : it_(std::move(that.it_))
- {}
- auto read() const -> decltype(*it_)
- {
- return *it_;
- }
- CPP_template(class J)(
- /// \pre
- requires ranges::sentinel_for<J, I>) //
- bool equal(cursor<J> const & that) const
- {
- return that.it_ == it_;
- }
- void next()
- {
- ++it_;
- }
- void prev()
- {
- --it_;
- }
- void advance(ranges::iter_difference_t<I> n)
- {
- it_ += n;
- }
- CPP_template(class J)(
- /// \pre
- requires ranges::sized_sentinel_for<J, I>) //
- ranges::iter_difference_t<I> distance_to(cursor<J> const & that) const
- {
- return that.it_ - it_;
- }
- };
- CPP_assert(ranges::detail::random_access_cursor<cursor<char *>>);
- template<class I>
- using iterator = ranges::basic_iterator<cursor<I>>;
- static_assert(std::is_same<iterator<char *>::iterator_category,
- std::random_access_iterator_tag>::value,
- "");
- void test()
- {
- using namespace ranges;
- iterator<char *> a(nullptr);
- iterator<char const *> b(nullptr);
- iterator<char const *> c(a);
- CPP_assert(
- std::is_same<std::iterator_traits<iterator<char *>>::pointer, char *>{});
- b = a;
- bool d = a == b;
- d = (a != b);
- detail::ignore_unused(
- d, //
- a < b, //
- a <= b, //
- a > b, //
- a >= b, //
- (a-b), //
- (b-a), //
- (a-a), //
- (b-b)); //
- }
- } // namespace test_random_access
- namespace test_weak_output
- {
- template<typename I>
- struct cursor
- {
- struct mixin : ranges::basic_mixin<cursor>
- {
- mixin() = default;
- // using ranges::basic_mixin<cursor>::basic_mixin;
- explicit mixin(cursor && cur)
- : ranges::basic_mixin<cursor>(static_cast<cursor &&>(cur))
- {}
- explicit mixin(cursor const & cur)
- : ranges::basic_mixin<cursor>(cur)
- {}
- explicit mixin(I i)
- : mixin(cursor{i})
- {}
- };
- cursor() = default;
- explicit cursor(I i)
- : it_(i)
- {}
- void write(ranges::iter_value_t<I> v) const
- {
- *it_ = v;
- }
- void next()
- {
- ++it_;
- }
- private:
- I it_;
- };
- CPP_assert(ranges::detail::output_cursor<cursor<char *>, char>);
- CPP_assert(!ranges::detail::sentinel_for_cursor<cursor<char *>, cursor<char *>>);
- template<class I>
- using iterator = ranges::basic_iterator<cursor<I>>;
- CPP_assert(ranges::output_iterator<iterator<char *>, char>);
- CPP_assert(!ranges::equality_comparable<iterator<char *>>);
- void test()
- {
- char buf[10];
- iterator<char *> i(buf);
- *i = 'h';
- ++i;
- *i = 'e';
- ++i;
- *i = 'l';
- ++i;
- *i = 'l';
- ++i;
- *i = 'o';
- ++i;
- *i = '\0';
- CHECK(0 == std::strcmp(buf, "hello"));
- }
- } // namespace test_weak_output
- namespace test_output
- {
- template<typename I>
- struct cursor
- {
- I it_;
- struct mixin : ranges::basic_mixin<cursor>
- {
- mixin() = default;
- //using ranges::basic_mixin<cursor>::basic_mixin;
- explicit mixin(cursor && cur)
- : ranges::basic_mixin<cursor>(static_cast<cursor &&>(cur))
- {}
- explicit mixin(cursor const & cur)
- : ranges::basic_mixin<cursor>(cur)
- {}
- mixin(I i)
- : mixin(cursor{i})
- {}
- };
- cursor() = default;
- explicit cursor(I i)
- : it_(i)
- {}
- CPP_template(class J)(
- /// \pre
- requires ranges::convertible_to<J, I>) //
- cursor(cursor<J> that)
- : it_(std::move(that.it_))
- {}
- using value_type = ranges::iter_value_t<I>;
- value_type read() const
- {
- return *it_;
- }
- void write(value_type v) const
- {
- *it_ = v;
- }
- I arrow() const
- {
- return it_;
- }
- void next()
- {
- ++it_;
- }
- bool equal(cursor const & that) const
- {
- return it_ == that.it_;
- }
- };
- CPP_assert(ranges::detail::output_cursor<cursor<char *>, char>);
- CPP_assert(ranges::detail::forward_cursor<cursor<char *>>);
- template<class I>
- using iterator = ranges::basic_iterator<cursor<I>>;
- CPP_assert(ranges::output_iterator<iterator<char *>, char>);
- CPP_assert(ranges::forward_iterator<iterator<char *>>);
- CPP_assert(std::is_same<std::iterator_traits<iterator<char *>>::pointer, char *>());
- void test()
- {
- char buf[10];
- iterator<char *> i(buf);
- *i = 'h';
- CHECK(*i == 'h');
- CHECK(*i == *i);
- ++i;
- *i = 'e';
- CHECK('e' == *i);
- ++i;
- *i = 'l';
- ++i;
- *i = 'l';
- ++i;
- *i = 'o';
- ++i;
- *i = '\0';
- CHECK(0 == std::strcmp(buf, "hello"));
- CHECK(i == iterator<char *>{buf + 5});
- ++i;
- CHECK(i != iterator<char *>{buf + 5});
- CHECK(i == iterator<char *>{buf + 6});
- }
- } // namespace test_output
- namespace test_move_only
- {
- struct MoveOnly
- {
- MoveOnly() = default;
- MoveOnly(MoveOnly &&) = default;
- MoveOnly(MoveOnly const &) = delete;
- MoveOnly & operator=(MoveOnly &&) = default;
- MoveOnly & operator=(MoveOnly const &) = delete;
- };
- template<typename I>
- struct zip1_cursor
- {
- I it_;
- struct mixin : ranges::basic_mixin<zip1_cursor>
- {
- mixin() = default;
- // using ranges::basic_mixin<zip1_cursor>::basic_mixin;
- explicit mixin(zip1_cursor && cur)
- : ranges::basic_mixin<zip1_cursor>(static_cast<zip1_cursor &&>(cur))
- {}
- explicit mixin(zip1_cursor const & cur)
- : ranges::basic_mixin<zip1_cursor>(cur)
- {}
- mixin(I i)
- : mixin(zip1_cursor{i})
- {}
- };
- zip1_cursor() = default;
- explicit zip1_cursor(I i)
- : it_(i)
- {}
- CPP_template(class J)(
- /// \pre
- requires ranges::convertible_to<J, I>) //
- zip1_cursor(zip1_cursor<J> that)
- : it_(std::move(that.it_))
- {}
- using value_type = std::tuple<ranges::iter_value_t<I>>;
- using reference = ranges::common_tuple<ranges::iter_reference_t<I>>;
- using rvalue_reference = ranges::common_tuple<ranges::iter_rvalue_reference_t<I>>;
- reference read() const
- {
- return reference{*it_};
- }
- rvalue_reference move() const
- {
- return rvalue_reference{ranges::iter_move(it_)};
- }
- void write(reference const & v) const
- {
- reference{ *it_} = v;
- }
- void write(value_type && v) const
- {
- reference{ *it_} = std::move(v);
- }
- void next()
- {
- ++it_;
- }
- bool equal(zip1_cursor const & that) const
- {
- return it_ == that.it_;
- }
- };
- CPP_assert(
- ranges::detail::output_cursor<zip1_cursor<MoveOnly *>, std::tuple<MoveOnly>
- &&>);
- CPP_assert(ranges::detail::forward_cursor<zip1_cursor<MoveOnly *>>);
- template<class I>
- using iterator = ranges::basic_iterator<zip1_cursor<I>>;
- CPP_assert(ranges::output_iterator<iterator<MoveOnly *>, std::tuple<MoveOnly> &&>);
- CPP_assert(ranges::forward_iterator<iterator<MoveOnly *>>);
- void test()
- {
- MoveOnly buf[10] = {};
- iterator<MoveOnly *> i(buf);
- *i = std::tuple<MoveOnly>{};
- ranges::common_tuple<MoveOnly &> x = *i;
- (void)x;
- std::tuple<MoveOnly> v = ranges::iter_move(i);
- *i = std::move(v);
- }
- } // namespace test_move_only
- namespace test_forward_sized
- {
- template<typename I>
- struct cursor
- {
- I it_;
- struct mixin : ranges::basic_mixin<cursor>
- {
- mixin() = default;
- // using ranges::basic_mixin<cursor>::basic_mixin;
- explicit mixin(cursor && cur)
- : ranges::basic_mixin<cursor>(static_cast<cursor &&>(cur))
- {}
- explicit mixin(cursor const & cur)
- : ranges::basic_mixin<cursor>(cur)
- {}
- mixin(I i)
- : mixin(cursor{i})
- {}
- };
- cursor() = default;
- explicit cursor(I i)
- : it_(i)
- {}
- CPP_template(class J)(
- /// \pre
- requires ranges::convertible_to<J, I>) //
- cursor(cursor<J> that)
- : it_(std::move(that.it_))
- {}
- auto read() const -> decltype(*it_)
- {
- return *it_;
- }
- CPP_template(class J)(
- /// \pre
- requires ranges::sentinel_for<J, I>) //
- bool equal(cursor<J> const & that) const
- {
- return that.it_ == it_;
- }
- void next()
- {
- ++it_;
- }
- CPP_template(class J)(
- /// \pre
- requires ranges::sized_sentinel_for<J, I>) //
- ranges::iter_difference_t<I> distance_to(cursor<J> const & that) const
- {
- return that.it_ - it_;
- }
- };
- CPP_assert(ranges::detail::sized_sentinel_for_cursor<cursor<char *>, cursor<char *>>);
- CPP_assert(ranges::detail::forward_cursor<cursor<char *>>);
- template<class I>
- using iterator = ranges::basic_iterator<cursor<I>>;
- static_assert(std::is_same<iterator<char *>::iterator_category,
- std::forward_iterator_tag>::value,
- "");
- void test()
- {
- using namespace ranges;
- iterator<char *> a(nullptr);
- iterator<char const *> b(nullptr);
- iterator<char const *> c(a);
- b = a;
- bool d = a == b;
- d = (a != b);
- detail::ignore_unused(
- d, //
- a < b, //
- a <= b, //
- a > b, //
- a >= b, //
- (a-b), //
- (b-a), //
- (a-a), //
- (b-b)); //
- }
- } // namespace test_forward_sized
- RANGES_DIAGNOSTIC_IGNORE_UNNEEDED_MEMBER
- void test_box()
- {
- struct A : ranges::box<int>
- {};
- CHECK(sizeof(A) == sizeof(int));
- struct empty
- {};
- struct B : ranges::box<empty>
- {
- int i;
- };
- CHECK(sizeof(B) == sizeof(int));
- B b1, b2;
- if(ranges::detail::box_compression<empty>() == ranges::detail::box_compress::coalesce)
- CHECK((&b1.get() == &b2.get()));
- struct nontrivial
- {
- nontrivial()
- {}
- };
- struct C : ranges::box<nontrivial>
- {
- int i;
- };
- CHECK(sizeof(C) == sizeof(int));
- C c1, c2;
- CHECK((&c1.get() != &c2.get()));
- {
- // empty but not trivial cursor that defines value_type:
- struct cursor
- {
- using value_type = int;
- cursor()
- {}
- int read() const
- {
- return 42;
- }
- void next()
- {}
- };
- CPP_assert(ranges::detail::box_compression<cursor>() ==
- ranges::detail::box_compress::ebo);
- CPP_assert(ranges::same_as<int, ranges::basic_iterator<cursor>::value_type>);
- }
- }
- int main()
- {
- using namespace ranges;
- std::cout << "\nTesting basic_iterator\n";
- ::test_weak_input::test();
- ::test_random_access::test();
- ::test_weak_output::test();
- ::test_output::test();
- ::test_move_only::test();
- ::test_forward_sized::test();
- ::test_box();
- return ::test_result();
- }
|