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