1 //===----------------------------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is dual licensed under the MIT and the University of Illinois Open 6 // Source Licenses. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // UNSUPPORTED: c++98, c++03, c++11, c++14 11 12 // XFAIL: with_system_cxx_lib=macosx10.12 13 // XFAIL: with_system_cxx_lib=macosx10.11 14 // XFAIL: with_system_cxx_lib=macosx10.10 15 // XFAIL: with_system_cxx_lib=macosx10.9 16 // XFAIL: with_system_cxx_lib=macosx10.7 17 // XFAIL: with_system_cxx_lib=macosx10.8 18 19 // <any> 20 21 // template <class ValueType> 22 // any& operator=(ValueType&&); 23 24 // Test value copy and move assignment. 25 26 #include <any> 27 #include <cassert> 28 29 #include "any_helpers.h" 30 #include "count_new.hpp" 31 #include "test_macros.h" 32 33 using std::any; 34 using std::any_cast; 35 36 template <class LHS, class RHS> 37 void test_assign_value() { 38 assert(LHS::count == 0); 39 assert(RHS::count == 0); 40 LHS::reset(); 41 RHS::reset(); 42 { 43 any lhs(LHS(1)); 44 any const rhs(RHS(2)); 45 46 assert(LHS::count == 1); 47 assert(RHS::count == 1); 48 assert(RHS::copied == 0); 49 50 lhs = rhs; 51 52 assert(RHS::copied == 1); 53 assert(LHS::count == 0); 54 assert(RHS::count == 2); 55 56 assertContains<RHS>(lhs, 2); 57 assertContains<RHS>(rhs, 2); 58 } 59 assert(LHS::count == 0); 60 assert(RHS::count == 0); 61 LHS::reset(); 62 RHS::reset(); 63 { 64 any lhs(LHS(1)); 65 any rhs(RHS(2)); 66 67 assert(LHS::count == 1); 68 assert(RHS::count == 1); 69 assert(RHS::moved == 1); 70 71 lhs = std::move(rhs); 72 73 assert(RHS::moved >= 1); 74 assert(RHS::copied == 0); 75 assert(LHS::count == 0); 76 assert(RHS::count == 1 + rhs.has_value()); 77 LIBCPP_ASSERT(!rhs.has_value()); 78 79 assertContains<RHS>(lhs, 2); 80 if (rhs.has_value()) 81 assertContains<RHS>(rhs, 0); 82 } 83 assert(LHS::count == 0); 84 assert(RHS::count == 0); 85 } 86 87 template <class RHS> 88 void test_assign_value_empty() { 89 assert(RHS::count == 0); 90 RHS::reset(); 91 { 92 any lhs; 93 RHS rhs(42); 94 assert(RHS::count == 1); 95 assert(RHS::copied == 0); 96 97 lhs = rhs; 98 99 assert(RHS::count == 2); 100 assert(RHS::copied == 1); 101 assert(RHS::moved >= 0); 102 assertContains<RHS>(lhs, 42); 103 } 104 assert(RHS::count == 0); 105 RHS::reset(); 106 { 107 any lhs; 108 RHS rhs(42); 109 assert(RHS::count == 1); 110 assert(RHS::moved == 0); 111 112 lhs = std::move(rhs); 113 114 assert(RHS::count == 2); 115 assert(RHS::copied == 0); 116 assert(RHS::moved >= 1); 117 assertContains<RHS>(lhs, 42); 118 } 119 assert(RHS::count == 0); 120 RHS::reset(); 121 } 122 123 124 template <class Tp, bool Move = false> 125 void test_assign_throws() { 126 #if !defined(TEST_HAS_NO_EXCEPTIONS) 127 auto try_throw = 128 [](any& lhs, auto&& rhs) { 129 try { 130 Move ? lhs = std::move(rhs) 131 : lhs = rhs; 132 assert(false); 133 } catch (my_any_exception const &) { 134 // do nothing 135 } catch (...) { 136 assert(false); 137 } 138 }; 139 // const lvalue to empty 140 { 141 any lhs; 142 Tp rhs(1); 143 assert(Tp::count == 1); 144 145 try_throw(lhs, rhs); 146 147 assert(Tp::count == 1); 148 assertEmpty<Tp>(lhs); 149 } 150 { 151 any lhs((small(2))); 152 Tp rhs(1); 153 assert(small::count == 1); 154 assert(Tp::count == 1); 155 156 try_throw(lhs, rhs); 157 158 assert(small::count == 1); 159 assert(Tp::count == 1); 160 assertContains<small>(lhs, 2); 161 } 162 { 163 any lhs((large(2))); 164 Tp rhs(1); 165 assert(large::count == 1); 166 assert(Tp::count == 1); 167 168 try_throw(lhs, rhs); 169 170 assert(large::count == 1); 171 assert(Tp::count == 1); 172 assertContains<large>(lhs, 2); 173 } 174 #endif 175 } 176 177 178 // Test that any& operator=(ValueType&&) is *never* selected for: 179 // * std::in_place type. 180 // * Non-copyable types 181 void test_sfinae_constraints() { 182 { // Only the constructors are required to SFINAE on in_place_t 183 using Tag = std::in_place_type_t<int>; 184 using RawTag = std::remove_reference_t<Tag>; 185 static_assert(std::is_assignable<std::any, RawTag&&>::value, ""); 186 } 187 { 188 struct Dummy { Dummy() = delete; }; 189 using T = std::in_place_type_t<Dummy>; 190 static_assert(std::is_assignable<std::any, T>::value, ""); 191 } 192 { 193 // Test that the ValueType&& constructor SFINAE's away when the 194 // argument is non-copyable 195 struct NoCopy { 196 NoCopy() = default; 197 NoCopy(NoCopy const&) = delete; 198 NoCopy(NoCopy&&) = default; 199 }; 200 static_assert(!std::is_assignable<std::any, NoCopy>::value, ""); 201 static_assert(!std::is_assignable<std::any, NoCopy&>::value, ""); 202 } 203 } 204 205 int main() { 206 test_assign_value<small1, small2>(); 207 test_assign_value<large1, large2>(); 208 test_assign_value<small, large>(); 209 test_assign_value<large, small>(); 210 test_assign_value_empty<small>(); 211 test_assign_value_empty<large>(); 212 test_assign_throws<small_throws_on_copy>(); 213 test_assign_throws<large_throws_on_copy>(); 214 test_assign_throws<throws_on_move, /* Move = */ true>(); 215 test_sfinae_constraints(); 216 } 217