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 // __non_propagating_cache& operator=(__non_propagating_cache const&); 12 13 // ADDITIONAL_COMPILE_FLAGS: -Wno-self-assign 14 15 #include <ranges> 16 17 #include <cassert> 18 #include <type_traits> 19 #include <utility> 20 21 template<bool NoexceptCopy> 22 struct CopyAssignable { 23 int x; CopyAssignableCopyAssignable24 constexpr explicit CopyAssignable(int i) : x(i) { } 25 CopyAssignable(CopyAssignable const&) = default; operator =CopyAssignable26 constexpr CopyAssignable& operator=(CopyAssignable const& other) noexcept(NoexceptCopy) { 27 x = other.x; 28 return *this; 29 } operator ==CopyAssignable30 constexpr bool operator==(CopyAssignable const& other) const { return x == other.x; } 31 }; 32 33 struct NotCopyAssignable { 34 int x; NotCopyAssignableNotCopyAssignable35 constexpr explicit NotCopyAssignable(int i) : x(i) { } 36 NotCopyAssignable(NotCopyAssignable const&) = default; 37 NotCopyAssignable& operator=(NotCopyAssignable const&) = delete; operator ==NotCopyAssignable38 constexpr bool operator==(NotCopyAssignable const& other) const { return x == other.x; } 39 }; 40 41 template <class T> test()42constexpr void test() { 43 using Cache = std::ranges::__non_propagating_cache<T>; 44 static_assert(std::is_nothrow_copy_assignable_v<Cache>); 45 46 // Assign to an empty cache 47 { 48 Cache a; a.__emplace(3); 49 Cache b; 50 51 Cache& result = (b = a); 52 assert(&result == &b); 53 assert(!b.__has_value()); // make sure we don't propagate 54 55 assert(a.__has_value()); // make sure we don't "steal" from the source 56 assert(*a == T{3}); // 57 } 58 59 // Assign to a non-empty cache 60 { 61 Cache a; a.__emplace(3); 62 Cache b; b.__emplace(5); 63 64 Cache& result = (b = a); 65 assert(&result == &b); 66 assert(!b.__has_value()); // make sure we don't propagate 67 68 assert(a.__has_value()); // make sure we don't "steal" from the source 69 assert(*a == T{3}); // 70 } 71 72 // Self-assignment should not do anything (case with empty cache) 73 { 74 Cache b; 75 Cache& result = (b = b); 76 assert(&result == &b); 77 assert(!b.__has_value()); 78 } 79 80 // Self-assignment should not do anything (case with non-empty cache) 81 { 82 Cache b; b.__emplace(5); 83 Cache& result = (b = b); 84 assert(&result == &b); 85 assert(b.__has_value()); 86 assert(*b == T{5}); 87 } 88 } 89 tests()90constexpr bool tests() { 91 test<CopyAssignable<true>>(); 92 test<CopyAssignable<false>>(); 93 test<NotCopyAssignable>(); 94 test<int>(); 95 return true; 96 } 97 main(int,char **)98int main(int, char**) { 99 static_assert(tests()); 100 tests(); 101 return 0; 102 } 103