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; 26 constexpr explicit DefaultConstructible(int j = 42) : i(j) {} 27 int *begin() const; 28 int *end() const; 29 }; 30 31 struct NotDefaultConstructible { 32 int i; 33 constexpr explicit NotDefaultConstructible(int j) : i(j) {} 34 int *begin() const; 35 int *end() const; 36 }; 37 38 struct MoveChecker { 39 int i; 40 constexpr explicit MoveChecker(int j) : i(j) {} 41 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 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 134 int main(int, char**) { 135 test(); 136 static_assert(test()); 137 138 return 0; 139 } 140