1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 // UNSUPPORTED: libcpp-no-concepts
11 // UNSUPPORTED: gcc-10
12 // UNSUPPORTED: libcpp-has-no-incomplete-ranges
13 
14 // constexpr V base() const& requires copy_constructible<V>;
15 // constexpr V base() &&;
16 
17 #include <ranges>
18 #include <cassert>
19 
20 #include "test_macros.h"
21 #include "test_iterators.h"
22 #include "test_range.h"
23 
24 struct ContiguousView : std::ranges::view_base {
25   int *ptr_;
26   constexpr ContiguousView(int* ptr) : ptr_(ptr) {}
27   constexpr ContiguousView(ContiguousView&&) = default;
28   constexpr ContiguousView& operator=(ContiguousView&&) = default;
29   friend constexpr int* begin(ContiguousView& view) { return view.ptr_; }
30   friend constexpr int* begin(ContiguousView const& view) { return view.ptr_; }
31   friend constexpr sentinel_wrapper<int*> end(ContiguousView& view) {
32     return sentinel_wrapper<int*>{view.ptr_ + 8};
33   }
34   friend constexpr sentinel_wrapper<int*> end(ContiguousView const& view) {
35     return sentinel_wrapper<int*>{view.ptr_ + 8};
36   }
37 };
38 
39 struct CopyableView : std::ranges::view_base {
40   int *ptr_;
41   constexpr CopyableView(int* ptr) : ptr_(ptr) {}
42   friend constexpr int* begin(CopyableView& view) { return view.ptr_; }
43   friend constexpr int* begin(CopyableView const& view) { return view.ptr_; }
44   friend constexpr sentinel_wrapper<int*> end(CopyableView& view) {
45     return sentinel_wrapper<int*>{view.ptr_ + 8};
46   }
47   friend constexpr sentinel_wrapper<int*> end(CopyableView const& view) {
48     return sentinel_wrapper<int*>{view.ptr_ + 8};
49   }
50 };
51 
52 constexpr bool hasLValueQualifiedBase(auto&& view) {
53     return requires { view.base(); };
54 }
55 
56 constexpr bool test() {
57   int buffer[8] = {1, 2, 3, 4, 5, 6, 7, 8};
58 
59   {
60     std::ranges::common_view<CopyableView> common(CopyableView{buffer});
61     assert(common.base().ptr_ == buffer);
62     assert(std::move(common).base().ptr_ == buffer);
63 
64     ASSERT_SAME_TYPE(decltype(common.base()), CopyableView);
65     ASSERT_SAME_TYPE(decltype(std::move(common).base()), CopyableView);
66     static_assert(hasLValueQualifiedBase(common));
67   }
68 
69   {
70     std::ranges::common_view<ContiguousView> common(ContiguousView{buffer});
71     assert(std::move(common).base().ptr_ == buffer);
72 
73     ASSERT_SAME_TYPE(decltype(std::move(common).base()), ContiguousView);
74     static_assert(!hasLValueQualifiedBase(common));
75   }
76 
77   {
78     const std::ranges::common_view<CopyableView> common(CopyableView{buffer});
79     assert(common.base().ptr_ == buffer);
80     assert(std::move(common).base().ptr_ == buffer);
81 
82     ASSERT_SAME_TYPE(decltype(common.base()), CopyableView);
83     ASSERT_SAME_TYPE(decltype(std::move(common).base()), CopyableView);
84     static_assert(hasLValueQualifiedBase(common));
85   }
86 
87   return true;
88 }
89 
90 int main(int, char**) {
91   test();
92   static_assert(test());
93 
94   return 0;
95 }
96