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