//===----------------------------------------------------------------------===// // // 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 && !common_range) // constexpr auto end() requires (!simple-view && common_range) // constexpr auto end() const requires range // constexpr auto end() const requires common_range #include #include #include #include #include #include "types.h" // | simple | common | v.end() | as_const(v) // | | | | .end() // |--------|--------|------------------|--------------- // | Y | Y | iterator | iterator // | Y | N | sentinel | sentinel // | N | Y | iterator | iterator // | N | N | sentinel | sentinel // !range template concept HasEnd = requires(T t) { t.end(); }; template concept HasConstEnd = requires(const T ct) { ct.end(); }; struct NoConstEndView : TupleBufferView { using TupleBufferView::TupleBufferView; constexpr std::tuple* begin() { return buffer_; } constexpr std::tuple* end() { return buffer_ + size_; } }; static_assert(HasEnd>); static_assert(!HasConstEnd>); constexpr bool test() { std::tuple 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 static_assert(std::same_as); static_assert(std::same_as); static_assert(std::same_as); } // 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 static_assert(std::same_as); static_assert(!std::same_as); static_assert(!std::same_as); } // !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 and iterator static_assert(!std::same_as); static_assert(std::same_as); static_assert(std::same_as); } // !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 and sentinel static_assert(!std::same_as); static_assert(!std::same_as); static_assert(!std::same_as); } // LWG 3406 elements_view::begin() and elements_view::end() have incompatible constraints { std::tuple 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; }