//===----------------------------------------------------------------------===// // // 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 // template // requires is_object_v // class ref_view; #include #include #include "test_macros.h" #include "test_iterators.h" int globalBuff[8]; template concept ValidRefView = requires { typename std::ranges::ref_view; }; struct Range { int start = 0; friend constexpr int* begin(Range const& range) { return globalBuff + range.start; } friend constexpr int* end(Range const&) { return globalBuff + 8; } friend constexpr int* begin(Range& range) { return globalBuff + range.start; } friend constexpr int* end(Range&) { return globalBuff + 8; } }; struct BeginOnly { friend int* begin(BeginOnly const&); friend int* begin(BeginOnly &); }; static_assert( ValidRefView); static_assert(!ValidRefView); static_assert(!ValidRefView); static_assert( ValidRefView); static_assert(std::derived_from, std::ranges::view_interface>>); struct RangeConvertible { operator Range& (); }; struct RValueRangeConvertible { operator Range&& (); }; static_assert( std::is_constructible_v, Range&>); static_assert( std::is_constructible_v, RangeConvertible>); static_assert(!std::is_constructible_v, RValueRangeConvertible>); struct ConstConvertibleToLValueAndRValue { operator Range& () const; operator Range&& () const; }; static_assert( std::is_convertible_v>); static_assert(!std::is_convertible_v>); static_assert(!std::is_convertible_v>); struct ForwardRange { constexpr forward_iterator begin() const { return forward_iterator(globalBuff); } constexpr forward_iterator end() const { return forward_iterator(globalBuff + 8); } }; struct Cpp17InputRange { struct sentinel { friend constexpr bool operator==(sentinel, cpp17_input_iterator iter) { return base(iter) == globalBuff + 8; } friend constexpr std::ptrdiff_t operator-(sentinel, cpp17_input_iterator) { return -8; } friend constexpr std::ptrdiff_t operator-(cpp17_input_iterator, sentinel) { return 8; } }; constexpr cpp17_input_iterator begin() const { return cpp17_input_iterator(globalBuff); } constexpr sentinel end() const { return {}; } }; struct Cpp20InputRange { struct sentinel { friend constexpr bool operator==(sentinel, const cpp20_input_iterator &iter) { return base(iter) == globalBuff + 8; } friend constexpr std::ptrdiff_t operator-(sentinel, const cpp20_input_iterator&) { return -8; } }; constexpr cpp20_input_iterator begin() const { return cpp20_input_iterator(globalBuff); } constexpr sentinel end() const { return {}; } }; template<> inline constexpr bool std::ranges::enable_borrowed_range = true; template concept EmptyIsInvocable = requires (std::ranges::ref_view view) { view.empty(); }; template concept SizeIsInvocable = requires (std::ranges::ref_view view) { view.size(); }; template concept DataIsInvocable = requires (std::ranges::ref_view view) { view.data(); }; // Testing ctad. static_assert(std::same_as())), std::ranges::ref_view>); constexpr bool test() { { // ref_view::base Range range; std::ranges::ref_view view{range}; assert(view.begin() == globalBuff); view.base() = Range{2}; assert(view.begin() == globalBuff + 2); } { // ref_view::begin Range range1; std::ranges::ref_view view1 = range1; assert(view1.begin() == globalBuff); ForwardRange range2; std::ranges::ref_view view2 = range2; assert(base(view2.begin()) == globalBuff); Cpp17InputRange range3; std::ranges::ref_view view3 = range3; assert(base(view3.begin()) == globalBuff); Cpp20InputRange range4; std::ranges::ref_view view4 = range4; assert(base(view4.begin()) == globalBuff); } { // ref_view::end Range range1; std::ranges::ref_view view1 = range1; assert(view1.end() == globalBuff + 8); ForwardRange range2; std::ranges::ref_view view2 = range2; assert(base(view2.end()) == globalBuff + 8); Cpp17InputRange range3; std::ranges::ref_view view3 = range3; assert(view3.end() == cpp17_input_iterator(globalBuff + 8)); Cpp20InputRange range4; std::ranges::ref_view view4 = range4; assert(view4.end() == cpp20_input_iterator(globalBuff + 8)); } { // ref_view::empty Range range{8}; std::ranges::ref_view view1 = range; assert(view1.empty()); ForwardRange range2; std::ranges::ref_view view2 = range2; assert(!view2.empty()); static_assert(!EmptyIsInvocable); static_assert(!EmptyIsInvocable); } { // ref_view::size Range range1{8}; std::ranges::ref_view view1 = range1; assert(view1.size() == 0); Range range2{2}; std::ranges::ref_view view2 = range2; assert(view2.size() == 6); static_assert(!SizeIsInvocable); } { // ref_view::data Range range1; std::ranges::ref_view view1 = range1; assert(view1.data() == globalBuff); Range range2{2}; std::ranges::ref_view view2 = range2; assert(view2.data() == globalBuff + 2); static_assert(!DataIsInvocable); } return true; } int main(int, char**) { test(); static_assert(test()); return 0; }