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