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