| //===----------------------------------------------------------------------===// |
| // |
| // 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 |
| |
| // constexpr auto end() requires (!simple-view<V> && !common_range<V>) |
| // constexpr auto end() requires (!simple-view<V> && common_range<V>) |
| // constexpr auto end() const requires range<const V> |
| // constexpr auto end() const requires common_range<const V> |
| |
| #include <cassert> |
| #include <iterator> |
| #include <ranges> |
| #include <type_traits> |
| #include <utility> |
| |
| #include "types.h" |
| |
| // | simple | common | v.end() | as_const(v) |
| // | | | | .end() |
| // |--------|--------|------------------|--------------- |
| // | Y | Y | iterator<true> | iterator<true> |
| // | Y | N | sentinel<true> | sentinel<true> |
| // | N | Y | iterator<false> | iterator<true> |
| // | N | N | sentinel<false> | sentinel<true> |
| |
| // !range<const V> |
| template <class T> |
| concept HasEnd = requires(T t) { t.end(); }; |
| |
| template <class T> |
| concept HasConstEnd = requires(const T ct) { ct.end(); }; |
| |
| struct NoConstEndView : TupleBufferView { |
| using TupleBufferView::TupleBufferView; |
| constexpr std::tuple<int>* begin() { return buffer_; } |
| constexpr std::tuple<int>* end() { return buffer_ + size_; } |
| }; |
| |
| static_assert(HasEnd<std::ranges::elements_view<NoConstEndView, 0>>); |
| static_assert(!HasConstEnd<std::ranges::elements_view<NoConstEndView, 0>>); |
| |
| constexpr bool test() { |
| std::tuple<int> buffer[] = {{1}, {2}, {3}}; |
| |
| // simple-view && common_view |
| { |
| SimpleCommon v{buffer}; |
| auto ev = std::views::elements<0>(v); |
| |
| auto it = ev.begin(); |
| decltype(auto) st = ev.end(); |
| assert(st == it + 3); |
| |
| auto const_it = std::as_const(ev).begin(); |
| decltype(auto) const_st = std::as_const(ev).end(); |
| assert(const_st == const_it + 3); |
| |
| // Both iterator<true> |
| static_assert(std::same_as<decltype(st), decltype(const_st)>); |
| static_assert(std::same_as<decltype(st), decltype(it)>); |
| static_assert(std::same_as<decltype(const_st), decltype(const_it)>); |
| } |
| |
| // simple-view && !common_view |
| { |
| SimpleNonCommon v{buffer}; |
| auto ev = std::views::elements<0>(v); |
| |
| auto it = ev.begin(); |
| decltype(auto) st = ev.end(); |
| assert(st == it + 3); |
| |
| auto const_it = std::as_const(ev).begin(); |
| decltype(auto) const_st = std::as_const(ev).end(); |
| assert(const_st == const_it + 3); |
| |
| // Both iterator<true> |
| static_assert(std::same_as<decltype(st), decltype(const_st)>); |
| static_assert(!std::same_as<decltype(st), decltype(it)>); |
| static_assert(!std::same_as<decltype(const_st), decltype(const_it)>); |
| } |
| |
| // !simple-view && common_view |
| { |
| NonSimpleCommon v{buffer}; |
| auto ev = std::views::elements<0>(v); |
| |
| auto it = ev.begin(); |
| decltype(auto) st = ev.end(); |
| assert(st == it + 3); |
| |
| auto const_it = std::as_const(ev).begin(); |
| decltype(auto) const_st = std::as_const(ev).end(); |
| assert(const_st == const_it + 3); |
| |
| // iterator<false> and iterator<true> |
| static_assert(!std::same_as<decltype(st), decltype(const_st)>); |
| static_assert(std::same_as<decltype(st), decltype(it)>); |
| static_assert(std::same_as<decltype(const_st), decltype(const_it)>); |
| } |
| |
| // !simple-view && !common_view |
| { |
| NonSimpleNonCommon v{buffer}; |
| auto ev = std::views::elements<0>(v); |
| |
| auto it = ev.begin(); |
| decltype(auto) st = ev.end(); |
| assert(st == it + 3); |
| |
| auto const_it = std::as_const(ev).begin(); |
| decltype(auto) const_st = std::as_const(ev).end(); |
| assert(const_st == const_it + 3); |
| |
| // sentinel<false> and sentinel<true> |
| static_assert(!std::same_as<decltype(st), decltype(const_st)>); |
| static_assert(!std::same_as<decltype(st), decltype(it)>); |
| static_assert(!std::same_as<decltype(const_st), decltype(const_it)>); |
| } |
| |
| // LWG 3406 elements_view::begin() and elements_view::end() have incompatible constraints |
| { |
| std::tuple<int, int> x[] = {{0, 0}}; |
| std::ranges::subrange r = {std::counted_iterator(x, 1), std::default_sentinel}; |
| auto v = r | std::views::elements<0>; |
| assert(v.begin() != v.end()); |
| } |
| |
| return true; |
| } |
| |
| int main(int, char**) { |
| test(); |
| static_assert(test()); |
| return 0; |
| } |