// Range v3 library // // Copyright Casey Carter 2016 // Copyright Eric Niebler 2018 // // 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 "../simple_test.hpp" #if defined(__clang__) RANGES_DIAGNOSTIC_IGNORE("-Wunused-const-variable") #endif void test_range_access_ambiguity() { std::vector> vri{}; using namespace ranges; (void)begin(vri); (void)end(vri); (void)cbegin(vri); (void)cend(vri); (void)rbegin(vri); (void)rend(vri); (void)crbegin(vri); (void)crend(vri); } void test_initializer_list() { std::initializer_list il = {0,1,2}; { int count = 0; for(auto p = ranges::begin(il), e = ranges::end(il); p != e; ++p) { CHECK(*p == count++); } } { int count = 3; for(auto p = ranges::rbegin(il), e = ranges::rend(il); p != e; ++p) { CHECK(*p == --count); } } CHECK(ranges::size(il) == std::size_t{3}); CHECK(ranges::data(il) == &*il.begin()); CHECK(ranges::empty(il) == false); } template void test_array(std::integer_sequence) { Value a[sizeof...(Is)] = { Is... }; { int count = 0; for(auto p = ranges::begin(a), e = ranges::end(a); p != e; ++p) { CHECK(*p == count++); } } { int count = sizeof...(Is); for(auto p = ranges::rbegin(a), e = ranges::rend(a); p != e; ++p) { CHECK(*p == --count); } } CHECK(ranges::size(a) == sizeof...(Is)); CHECK(ranges::data(a) == a + 0); CHECK(ranges::empty(a) == false); } namespace begin_testing { template CPP_requires(can_begin_, requires(R&& r) // ( ranges::begin((R &&) r) )); template CPP_concept can_begin = CPP_requires_ref(can_begin_, R); template CPP_requires(can_cbegin_, requires(R&& r) // ( ranges::cbegin((R &&) r) )); template CPP_concept can_cbegin = CPP_requires_ref(can_cbegin_, R); struct A { int* begin(); int* end(); int const * begin() const; int const * end() const; }; struct B : A {}; void* begin(B&); struct C : A {}; void begin(C&); struct D : A {}; char* begin(D&); void test() { // Valid CPP_assert(can_begin); CPP_assert(ranges::same_as())), int*>); CPP_assert(can_begin); CPP_assert(ranges::same_as())), int const *>); CPP_assert(can_cbegin); CPP_assert(ranges::same_as())), int const *>); CPP_assert(can_cbegin); CPP_assert(ranges::same_as())), int const *>); #ifndef RANGES_WORKAROUND_MSVC_573728 // Ill-formed: array rvalue CPP_assert(!can_begin); CPP_assert(!can_begin); CPP_assert(!can_cbegin); CPP_assert(!can_cbegin); #endif // RANGES_WORKAROUND_MSVC_573728 // Valid: only member begin CPP_assert(can_begin); CPP_assert(!can_begin); CPP_assert(ranges::same_as())), int*>); CPP_assert(can_begin); CPP_assert(!can_begin); CPP_assert(ranges::same_as())), int const *>); // Valid: Both member and non-member begin, but non-member returns non-Iterator. CPP_assert(can_begin); CPP_assert(!can_begin); CPP_assert(ranges::same_as())), int*>); CPP_assert(can_begin); CPP_assert(!can_begin); CPP_assert(ranges::same_as())), int const *>); // Valid: Both member and non-member begin, but non-member returns non-Iterator. CPP_assert(can_begin); CPP_assert(!can_begin); CPP_assert(can_begin); CPP_assert(!can_begin); // Valid: Prefer member begin CPP_assert(can_begin); CPP_assert(!can_begin); CPP_assert(ranges::same_as()))>); CPP_assert(can_begin); CPP_assert(!can_begin); CPP_assert(ranges::same_as()))>); { using T = std::initializer_list; // Valid: begin accepts lvalue initializer_list CPP_assert(ranges::same_as()))>); CPP_assert(ranges::same_as()))>); CPP_assert(!can_begin); CPP_assert(!can_begin); } CPP_assert(can_begin&>); CPP_assert(can_begin&>); CPP_assert(can_begin>); CPP_assert(can_begin>); CPP_assert(can_cbegin&>); CPP_assert(can_cbegin&>); CPP_assert(can_cbegin>); CPP_assert(can_cbegin>); CPP_assert(can_begin&>); CPP_assert(can_begin&>); CPP_assert(can_begin>); CPP_assert(can_begin>); CPP_assert(can_cbegin&>); CPP_assert(can_cbegin&>); CPP_assert(can_cbegin>); CPP_assert(can_cbegin>); // TODO // CPP_assert(can_begin&>); // CPP_assert(can_begin&>); // CPP_assert(can_begin>); // CPP_assert(can_begin>); // CPP_assert(can_cbegin&>); // CPP_assert(can_cbegin&>); // CPP_assert(can_cbegin>); // CPP_assert(can_cbegin>); } } // namespace begin_testing namespace X { template struct array { T elements_[N]; constexpr bool empty() const noexcept { return N == 0; } constexpr T* data() noexcept { return elements_; } constexpr T const *data() const noexcept { return elements_; } }; template constexpr T* begin(array &a) noexcept { return a.elements_; } template constexpr T* end(array &a) noexcept { return a.elements_ + N; } template constexpr T const *begin(array const &a) noexcept { return a.elements_; } template constexpr T const *end(array const &a) noexcept { return a.elements_ + N; } } // namespace X using I = int*; using CI = int const *; CPP_assert(ranges::input_or_output_iterator); CPP_assert(ranges::input_or_output_iterator); #if defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201603L void test_string_view_p0970() { // basic_string_views are non-dangling using I2 = ranges::iterator_t; CPP_assert(ranges::same_as()))>); CPP_assert(ranges::same_as()))>); CPP_assert(ranges::same_as()))>); CPP_assert(ranges::same_as()))>); { const char hw[] = "Hello, World!"; auto result = ranges::find(std::string_view{hw}, 'W'); CPP_assert(ranges::same_as); CHECK(result == std::string_view{hw}.begin() + 7); } } #endif int main() { using namespace ranges; static constexpr X::array some_ints = {{0,1,2,3}}; CPP_assert(begin_testing::can_begin &>); CPP_assert(begin_testing::can_begin const &>); CPP_assert(!begin_testing::can_begin>); CPP_assert(!begin_testing::can_begin const>); CPP_assert(begin_testing::can_cbegin &>); CPP_assert(begin_testing::can_cbegin const &>); CPP_assert(!begin_testing::can_cbegin>); CPP_assert(!begin_testing::can_cbegin const>); constexpr auto first = begin(some_ints); constexpr auto last = end(some_ints); CPP_assert(ranges::same_as); CPP_assert(ranges::same_as); static_assert(first == cbegin(some_ints), ""); static_assert(last == cend(some_ints), ""); static_assert(noexcept(begin(some_ints)), ""); static_assert(noexcept(end(some_ints)), ""); static_assert(noexcept(cbegin(some_ints)), ""); static_assert(noexcept(cend(some_ints)), ""); static_assert(noexcept(empty(some_ints)), ""); static_assert(noexcept(data(some_ints)), ""); constexpr bool output = false; static_assert(!empty(some_ints), ""); if(output) std::cout << '{'; auto is_first = true; auto count = 0; for(auto&& i : some_ints) { CHECK(i == count++); if(is_first) is_first = false; else if(output) std::cout << ", "; if(output) std::cout << i; } if(output) std::cout << "}\n"; test_initializer_list(); test_array(std::make_integer_sequence{}); test_array(std::make_integer_sequence{}); begin_testing::test(); #if defined(__cpp_lib_string_view) && __cpp_lib_string_view >= 201603L test_string_view_p0970(); #endif return ::test_result(); }