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-has-no-incomplete-ranges
11 
12 // owning_view() requires default_initializable<R> = default;
13 // constexpr owning_view(R&& t);
14 
15 #include <ranges>
16 
17 #include <cassert>
18 #include <concepts>
19 #include <type_traits>
20 #include <utility>
21 
22 #include "test_macros.h"
23 
24 struct DefaultConstructible {
25   int i;
DefaultConstructibleDefaultConstructible26   constexpr explicit DefaultConstructible(int j = 42) : i(j) {}
27   int *begin() const;
28   int *end() const;
29 };
30 
31 struct NotDefaultConstructible {
32   int i;
NotDefaultConstructibleNotDefaultConstructible33   constexpr explicit NotDefaultConstructible(int j) : i(j) {}
34   int *begin() const;
35   int *end() const;
36 };
37 
38 struct MoveChecker {
39   int i;
MoveCheckerMoveChecker40   constexpr explicit MoveChecker(int j) : i(j) {}
MoveCheckerMoveChecker41   constexpr MoveChecker(MoveChecker&& v) : i(std::exchange(v.i, -1)) {}
42   MoveChecker& operator=(MoveChecker&&);
43   int *begin() const;
44   int *end() const;
45 };
46 
47 struct NoexceptChecker {
48   int *begin() const;
49   int *end() const;
50 };
51 
test()52 constexpr bool test()
53 {
54   {
55     using OwningView = std::ranges::owning_view<DefaultConstructible>;
56     static_assert(std::is_constructible_v<OwningView>);
57     static_assert(std::default_initializable<OwningView>);
58     static_assert(std::movable<OwningView>);
59     static_assert(std::is_trivially_move_constructible_v<OwningView>);
60     static_assert(std::is_trivially_move_assignable_v<OwningView>);
61     static_assert(!std::is_copy_constructible_v<OwningView>);
62     static_assert(!std::is_copy_assignable_v<OwningView>);
63     static_assert(!std::is_constructible_v<OwningView, int>);
64     static_assert(!std::is_constructible_v<OwningView, DefaultConstructible&>);
65     static_assert(std::is_constructible_v<OwningView, DefaultConstructible&&>);
66     static_assert(!std::is_convertible_v<int, OwningView>);
67     static_assert(std::is_convertible_v<DefaultConstructible&&, OwningView>);
68     {
69       OwningView ov;
70       assert(ov.base().i == 42);
71     }
72     {
73       OwningView ov = OwningView(DefaultConstructible(1));
74       assert(ov.base().i == 1);
75     }
76   }
77   {
78     using OwningView = std::ranges::owning_view<NotDefaultConstructible>;
79     static_assert(!std::is_constructible_v<OwningView>);
80     static_assert(!std::default_initializable<OwningView>);
81     static_assert(std::movable<OwningView>);
82     static_assert(std::is_trivially_move_constructible_v<OwningView>);
83     static_assert(std::is_trivially_move_assignable_v<OwningView>);
84     static_assert(!std::is_copy_constructible_v<OwningView>);
85     static_assert(!std::is_copy_assignable_v<OwningView>);
86     static_assert(!std::is_constructible_v<OwningView, int>);
87     static_assert(!std::is_constructible_v<OwningView, NotDefaultConstructible&>);
88     static_assert(std::is_constructible_v<OwningView, NotDefaultConstructible&&>);
89     static_assert(!std::is_convertible_v<int, OwningView>);
90     static_assert(std::is_convertible_v<NotDefaultConstructible&&, OwningView>);
91     {
92       OwningView ov = OwningView(NotDefaultConstructible(1));
93       assert(ov.base().i == 1);
94     }
95   }
96   {
97     using OwningView = std::ranges::owning_view<MoveChecker>;
98     static_assert(!std::is_constructible_v<OwningView>);
99     static_assert(!std::default_initializable<OwningView>);
100     static_assert(std::movable<OwningView>);
101     static_assert(!std::is_trivially_move_constructible_v<OwningView>);
102     static_assert(!std::is_trivially_move_assignable_v<OwningView>);
103     static_assert(!std::is_copy_constructible_v<OwningView>);
104     static_assert(!std::is_copy_assignable_v<OwningView>);
105     static_assert(!std::is_constructible_v<OwningView, int>);
106     static_assert(!std::is_constructible_v<OwningView, MoveChecker&>);
107     static_assert(std::is_constructible_v<OwningView, MoveChecker&&>);
108     static_assert(!std::is_convertible_v<int, OwningView>);
109     static_assert(std::is_convertible_v<MoveChecker&&, OwningView>);
110     {
111       // Check that the constructor does indeed move from the target object.
112       auto m = MoveChecker(42);
113       OwningView ov = OwningView(std::move(m));
114       assert(ov.base().i == 42);
115       assert(m.i == -1);
116     }
117   }
118   {
119     // Check that the defaulted constructors are (not) noexcept when appropriate.
120 
121     static_assert( std::is_nothrow_constructible_v<NoexceptChecker>); // therefore,
122     static_assert( std::is_nothrow_constructible_v<std::ranges::owning_view<NoexceptChecker>>);
123     static_assert(!std::is_nothrow_constructible_v<DefaultConstructible>); // therefore,
124     static_assert(!std::is_nothrow_constructible_v<std::ranges::owning_view<DefaultConstructible>>);
125 
126     static_assert( std::is_nothrow_move_constructible_v<NoexceptChecker>); // therefore,
127     static_assert( std::is_nothrow_move_constructible_v<std::ranges::owning_view<NoexceptChecker>>);
128     static_assert(!std::is_nothrow_move_constructible_v<MoveChecker>); // therefore,
129     static_assert(!std::is_nothrow_move_constructible_v<std::ranges::owning_view<MoveChecker>>);
130   }
131   return true;
132 }
133 
main(int,char **)134 int main(int, char**) {
135   test();
136   static_assert(test());
137 
138   return 0;
139 }
140