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