//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17 // std::views::counted; #include #include #include #include #include #include #include #include "test_macros.h" #include "test_iterators.h" struct RvalueConvertible { RvalueConvertible(const RvalueConvertible&) = delete; operator int() &&; }; struct LvalueConvertible { LvalueConvertible(const LvalueConvertible&) = delete; operator int() &; }; struct OnlyExplicitlyConvertible { explicit operator int() const; }; template concept CountedInvocable = requires (Ts&&... ts) { std::views::counted(std::forward(ts)...); }; constexpr bool test() { int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8}; { static_assert(std::addressof(std::views::counted) == std::addressof(std::ranges::views::counted)); static_assert( CountedInvocable); static_assert(!CountedInvocable); static_assert( CountedInvocable); static_assert( CountedInvocable); static_assert(!CountedInvocable); static_assert(!CountedInvocable); static_assert(!CountedInvocable); static_assert(!CountedInvocable); static_assert(!CountedInvocable); static_assert(!CountedInvocable<>); } { auto c1 = std::views::counted(buffer, 3); auto c2 = std::views::counted(std::as_const(buffer), 3); ASSERT_SAME_TYPE(decltype(c1), std::span); ASSERT_SAME_TYPE(decltype(c2), std::span); assert(c1.data() == buffer && c1.size() == 3); assert(c2.data() == buffer && c2.size() == 3); } { auto it = contiguous_iterator(buffer); auto cit = contiguous_iterator(buffer); auto c1 = std::views::counted(it, 3); auto c2 = std::views::counted(std::as_const(it), 3); auto c3 = std::views::counted(std::move(it), 3); auto c4 = std::views::counted(contiguous_iterator(buffer), 3); auto c5 = std::views::counted(cit, 3); auto c6 = std::views::counted(std::as_const(cit), 3); auto c7 = std::views::counted(std::move(cit), 3); auto c8 = std::views::counted(contiguous_iterator(buffer), 3); ASSERT_SAME_TYPE(decltype(c1), std::span); ASSERT_SAME_TYPE(decltype(c2), std::span); ASSERT_SAME_TYPE(decltype(c3), std::span); ASSERT_SAME_TYPE(decltype(c4), std::span); ASSERT_SAME_TYPE(decltype(c5), std::span); ASSERT_SAME_TYPE(decltype(c6), std::span); ASSERT_SAME_TYPE(decltype(c7), std::span); ASSERT_SAME_TYPE(decltype(c8), std::span); assert(c1.data() == buffer && c1.size() == 3); assert(c2.data() == buffer && c2.size() == 3); assert(c3.data() == buffer && c3.size() == 3); assert(c4.data() == buffer && c4.size() == 3); assert(c5.data() == buffer && c5.size() == 3); assert(c6.data() == buffer && c6.size() == 3); assert(c7.data() == buffer && c7.size() == 3); assert(c8.data() == buffer && c8.size() == 3); } { auto it = random_access_iterator(buffer); auto cit = random_access_iterator(buffer); auto it_copy = it; auto cit_copy = cit; auto c1 = std::views::counted(it, 3); auto c2 = std::views::counted(std::as_const(it), 3); auto c3 = std::views::counted(std::move(it_copy), 3); auto c4 = std::views::counted(random_access_iterator(buffer), 3); auto c5 = std::views::counted(cit, 3); auto c6 = std::views::counted(std::as_const(cit), 3); auto c7 = std::views::counted(std::move(cit_copy), 3); auto c8 = std::views::counted(random_access_iterator(buffer), 3); ASSERT_SAME_TYPE(decltype(c1), std::ranges::subrange>); ASSERT_SAME_TYPE(decltype(c2), std::ranges::subrange>); ASSERT_SAME_TYPE(decltype(c3), std::ranges::subrange>); ASSERT_SAME_TYPE(decltype(c4), std::ranges::subrange>); ASSERT_SAME_TYPE(decltype(c5), std::ranges::subrange>); ASSERT_SAME_TYPE(decltype(c6), std::ranges::subrange>); ASSERT_SAME_TYPE(decltype(c7), std::ranges::subrange>); ASSERT_SAME_TYPE(decltype(c8), std::ranges::subrange>); assert(c1.begin() == it && c1.end() == it + 3); assert(c2.begin() == it && c2.end() == it + 3); assert(c3.begin() == it && c3.end() == it + 3); assert(c4.begin() == it && c4.end() == it + 3); assert(c5.begin() == cit && c5.end() == cit + 3); assert(c6.begin() == cit && c6.end() == cit + 3); assert(c7.begin() == cit && c7.end() == cit + 3); assert(c8.begin() == cit && c8.end() == cit + 3); } { auto it = bidirectional_iterator(buffer); auto cit = bidirectional_iterator(buffer); auto it_copy = it; auto cit_copy = cit; auto c1 = std::views::counted(it, 3); auto c2 = std::views::counted(std::as_const(it), 3); auto c3 = std::views::counted(std::move(it_copy), 3); auto c4 = std::views::counted(bidirectional_iterator(buffer), 3); auto c5 = std::views::counted(cit, 3); auto c6 = std::views::counted(std::as_const(cit), 3); auto c7 = std::views::counted(std::move(cit_copy), 3); auto c8 = std::views::counted(bidirectional_iterator(buffer), 3); using Expected = std::ranges::subrange, std::default_sentinel_t>; using ConstExpected = std::ranges::subrange, std::default_sentinel_t>; ASSERT_SAME_TYPE(decltype(c1), Expected); ASSERT_SAME_TYPE(decltype(c2), Expected); ASSERT_SAME_TYPE(decltype(c3), Expected); ASSERT_SAME_TYPE(decltype(c4), Expected); ASSERT_SAME_TYPE(decltype(c5), ConstExpected); ASSERT_SAME_TYPE(decltype(c6), ConstExpected); ASSERT_SAME_TYPE(decltype(c7), ConstExpected); ASSERT_SAME_TYPE(decltype(c8), ConstExpected); assert(c1.begin().base() == it && c1.size() == 3); assert(c2.begin().base() == it && c2.size() == 3); assert(c3.begin().base() == it && c3.size() == 3); assert(c4.begin().base() == it && c4.size() == 3); assert(c5.begin().base() == cit && c5.size() == 3); assert(c6.begin().base() == cit && c6.size() == 3); assert(c7.begin().base() == cit && c7.size() == 3); assert(c8.begin().base() == cit && c8.size() == 3); } { auto it = cpp17_output_iterator(buffer); auto it_copy = it; auto c1 = std::views::counted(it, 3); auto c2 = std::views::counted(std::as_const(it), 3); auto c3 = std::views::counted(std::move(it_copy), 3); auto c4 = std::views::counted(cpp17_output_iterator(buffer), 3); using Expected = std::ranges::subrange, std::default_sentinel_t>; ASSERT_SAME_TYPE(decltype(c1), Expected); ASSERT_SAME_TYPE(decltype(c2), Expected); ASSERT_SAME_TYPE(decltype(c3), Expected); ASSERT_SAME_TYPE(decltype(c4), Expected); assert(base(c1.begin().base()) == buffer && c1.size() == 3); assert(base(c2.begin().base()) == buffer && c2.size() == 3); assert(base(c3.begin().base()) == buffer && c3.size() == 3); assert(base(c4.begin().base()) == buffer && c4.size() == 3); } { auto it = cpp17_input_iterator(buffer); auto it_copy = it; auto c1 = std::views::counted(it, 3); auto c2 = std::views::counted(std::as_const(it), 3); auto c3 = std::views::counted(std::move(it_copy), 3); auto c4 = std::views::counted(cpp17_input_iterator(buffer), 3); using Expected = std::ranges::subrange, std::default_sentinel_t>; ASSERT_SAME_TYPE(decltype(c1), Expected); ASSERT_SAME_TYPE(decltype(c2), Expected); ASSERT_SAME_TYPE(decltype(c3), Expected); ASSERT_SAME_TYPE(decltype(c4), Expected); assert(base(c1.begin().base()) == buffer && c1.size() == 3); assert(base(c2.begin().base()) == buffer && c2.size() == 3); assert(base(c3.begin().base()) == buffer && c3.size() == 3); assert(base(c4.begin().base()) == buffer && c4.size() == 3); } { auto it = cpp20_input_iterator(buffer); static_assert(!std::copyable>); static_assert(!CountedInvocable&, int>); static_assert(!CountedInvocable&, int>); auto c3 = std::views::counted(std::move(it), 3); auto c4 = std::views::counted(cpp20_input_iterator(buffer), 3); using Expected = std::ranges::subrange, std::default_sentinel_t>; ASSERT_SAME_TYPE(decltype(c3), Expected); ASSERT_SAME_TYPE(decltype(c4), Expected); assert(base(c3.begin().base()) == buffer && c3.size() == 3); assert(base(c4.begin().base()) == buffer && c4.size() == 3); } return true; } int main(int, char**) { test(); static_assert(test()); return 0; }