// Range v3 library // // Copyright Tobias Mayer 2016 // Copyright Casey Carter 2016 // // 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 #include #include #include #include #include #include #include #include #include #include #include #include "../simple_test.hpp" #include "../test_utils.hpp" using namespace ranges; namespace { namespace ebo_test { struct empty1 {}; struct empty2 {}; struct refines : empty1, empty2 {}; } constexpr bool broken_ebo = sizeof(ebo_test::refines) > sizeof(ebo_test::empty1); constexpr auto N = 7; constexpr auto K = 3; CPP_assert(K < N); template void test_size(Adapted& a, std::true_type) { CPP_assert(sized_range); CHECK(size(a), unsigned(N - K + 1)); } template void test_size(Adapted&, std::false_type) {} template void test_common(Adapted& a, std::true_type) { CPP_assert(common_range); } // template // void test_common(Adapted&, std::false_type) // {} template void test_prev(Adapted& a, iterator_t const& it, std::true_type) { CPP_assert(bidirectional_range); ::check_equal(*ranges::prev(it, 3), views::iota(N - K - 2, N - 2)); } template void test_prev(Adapted&, iterator_t const&, std::false_type) {} template struct size_compare_ { iterator_t iter1_; iterator_t iter2_; range_difference_t dist_; }; template struct size_compare_ { iterator_t iter1_; range_difference_t dist_; }; template using size_compare = size_compare_ || (bidirectional_range && common_range)>; template void test_finite(ToBase to_base) { auto v = to_base(views::iota(0,N)); using Base = decltype(v); auto rng = v | views::sliding(K); using Adapted = decltype(rng); test_size(rng, meta::bool_>{}); using IterTagOfBase = meta::if_c>, std::random_access_iterator_tag, iterator_tag_of>>; CPP_assert(same_as< IterTagOfBase, iterator_tag_of>>); auto it = ranges::begin(rng); test_common(rng, meta::bool_>{}); for (auto i = 0; i <= N - K; ++i) { ::check_equal(*it++, views::iota(i, i + K)); } CHECK(it == ranges::end(rng)); test_prev(rng, it, meta::bool_>{}); if (!broken_ebo) { CHECK(sizeof(it) == sizeof(size_compare)); } } } void bug_975() { std::vector v{2.0, 2.0, 3.0, 1.0}; std::vector i{1, 2, 1, 2}; std::vector t{1, 1, 2, 2}; { using namespace ranges; auto vals = views::zip(v, i, t); using T = std::tuple; auto g = vals | views::chunk_by( [](T t1, T t2) { return std::get<2>(t1) == std::get<2>(t2); } ); auto windows = views::sliding(g, 2); auto it = std::begin(windows); (void)it; } } int main() { test_finite(to>()); test_finite(to>()); test_finite(to>()); test_finite(identity{}); { // An infinite, cyclic range with cycle length == 1 auto rng = views::repeat(5) | views::sliding(K); CPP_assert(random_access_range); auto it = rng.begin(); CPP_assert(random_access_iterator); #if defined(__GNUC__) && !defined(__clang__) && \ ((__GNUC__ == 6 && __GNUC_MINOR__ < 3) || __GNUC__ < 6) // Avoid https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78047 { auto deref = *it; auto i = deref.begin(); for (auto n = 0; n < K; ++n) { RANGES_ENSURE(i != deref.end()); CHECK(*i == 5); ++i; } CHECK(i == deref.end()); } auto it2 = next(it, 42); CHECK(it != it2); { auto deref = *it; auto i = deref.begin(); for (auto n = 0; n < K; ++n) { RANGES_ENSURE(i != deref.end()); CHECK(*i == 5); ++i; } CHECK(i == deref.end()); } #else ::check_equal(*it, views::repeat_n(5, K)); auto it2 = next(it, 42); CHECK(it != it2); ::check_equal(*it2, views::repeat_n(5, K)); #endif } { // An infinite, cyclic range with cycle length == K auto rng = views::iota(0, K) | views::cycle | views::sliding(K); CPP_assert(random_access_range); auto it = rng.begin(); CPP_assert(random_access_iterator); for (auto i = 0; i < 42; ++i) { ::check_equal(*it++, {0,1,2}); ::check_equal(*it++, {1,2,0}); ::check_equal(*it++, {2,0,1}); } auto it2 = next(it, 42 * K); ::check_equal(*it2, {0,1,2}); } { // An infinite, cyclic range with cycle length > K auto rng = views::iota(0,7) | views::cycle | views::sliding(K); //[0,1,2],[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,0],[6,0,1],... auto it = rng.begin(); CPP_assert(random_access_iterator); ::check_equal(*it, {0,1,2}); ::check_equal(*next(it, 2), {2,3,4}); ::check_equal(*next(it,16), {2,3,4}); ::check_equal(*next(it,27), {6,0,1}); } return ::test_result(); }