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 // <optional> 12 13 // template <class T> void swap(optional<T>& x, optional<T>& y) 14 // noexcept(noexcept(x.swap(y))); 15 16 #include <optional> 17 #include <type_traits> 18 #include <cassert> 19 20 #include "test_macros.h" 21 #include "archetypes.hpp" 22 23 using std::optional; 24 25 class X 26 { 27 int i_; 28 public: 29 static unsigned dtor_called; 30 X(int i) : i_(i) {} 31 X(X&& x) = default; 32 X& operator=(X&&) = default; 33 ~X() {++dtor_called;} 34 35 friend bool operator==(const X& x, const X& y) {return x.i_ == y.i_;} 36 }; 37 38 unsigned X::dtor_called = 0; 39 40 class Y 41 { 42 int i_; 43 public: 44 static unsigned dtor_called; 45 Y(int i) : i_(i) {} 46 Y(Y&&) = default; 47 ~Y() {++dtor_called;} 48 49 friend constexpr bool operator==(const Y& x, const Y& y) {return x.i_ == y.i_;} 50 friend void swap(Y& x, Y& y) {std::swap(x.i_, y.i_);} 51 }; 52 53 unsigned Y::dtor_called = 0; 54 55 class Z 56 { 57 int i_; 58 public: 59 Z(int i) : i_(i) {} 60 Z(Z&&) { TEST_THROW(7);} 61 62 friend constexpr bool operator==(const Z& x, const Z& y) {return x.i_ == y.i_;} 63 friend void swap(Z&, Z&) { TEST_THROW(6);} 64 }; 65 66 67 struct NonSwappable { 68 NonSwappable(NonSwappable const&) = delete; 69 }; 70 void swap(NonSwappable&, NonSwappable&) = delete; 71 72 void test_swap_sfinae() { 73 using std::optional; 74 { 75 using T = TestTypes::TestType; 76 static_assert(std::is_swappable_v<optional<T>>, ""); 77 } 78 { 79 using T = TestTypes::MoveOnly; 80 static_assert(std::is_swappable_v<optional<T>>, ""); 81 } 82 { 83 using T = TestTypes::Copyable; 84 static_assert(std::is_swappable_v<optional<T>>, ""); 85 } 86 { 87 using T = TestTypes::NoCtors; 88 static_assert(!std::is_swappable_v<optional<T>>, ""); 89 } 90 { 91 using T = NonSwappable; 92 static_assert(!std::is_swappable_v<optional<T>>, ""); 93 } 94 { 95 // Even thought CopyOnly has deleted move operations, those operations 96 // cause optional<CopyOnly> to have implicitly deleted move operations 97 // that decay into copies. 98 using T = TestTypes::CopyOnly; 99 using Opt = optional<T>; 100 T::reset(); 101 Opt L(101), R(42); 102 T::reset_constructors(); 103 std::swap(L, R); 104 assert(L->value == 42); 105 assert(R->value == 101); 106 assert(T::copy_constructed == 1); 107 assert(T::constructed == T::copy_constructed); 108 assert(T::assigned == 2); 109 assert(T::assigned == T::copy_assigned); 110 } 111 } 112 113 int main() 114 { 115 test_swap_sfinae(); 116 { 117 optional<int> opt1; 118 optional<int> opt2; 119 static_assert(noexcept(swap(opt1, opt2)) == true, ""); 120 assert(static_cast<bool>(opt1) == false); 121 assert(static_cast<bool>(opt2) == false); 122 swap(opt1, opt2); 123 assert(static_cast<bool>(opt1) == false); 124 assert(static_cast<bool>(opt2) == false); 125 } 126 { 127 optional<int> opt1(1); 128 optional<int> opt2; 129 static_assert(noexcept(swap(opt1, opt2)) == true, ""); 130 assert(static_cast<bool>(opt1) == true); 131 assert(*opt1 == 1); 132 assert(static_cast<bool>(opt2) == false); 133 swap(opt1, opt2); 134 assert(static_cast<bool>(opt1) == false); 135 assert(static_cast<bool>(opt2) == true); 136 assert(*opt2 == 1); 137 } 138 { 139 optional<int> opt1; 140 optional<int> opt2(2); 141 static_assert(noexcept(swap(opt1, opt2)) == true, ""); 142 assert(static_cast<bool>(opt1) == false); 143 assert(static_cast<bool>(opt2) == true); 144 assert(*opt2 == 2); 145 swap(opt1, opt2); 146 assert(static_cast<bool>(opt1) == true); 147 assert(*opt1 == 2); 148 assert(static_cast<bool>(opt2) == false); 149 } 150 { 151 optional<int> opt1(1); 152 optional<int> opt2(2); 153 static_assert(noexcept(swap(opt1, opt2)) == true, ""); 154 assert(static_cast<bool>(opt1) == true); 155 assert(*opt1 == 1); 156 assert(static_cast<bool>(opt2) == true); 157 assert(*opt2 == 2); 158 swap(opt1, opt2); 159 assert(static_cast<bool>(opt1) == true); 160 assert(*opt1 == 2); 161 assert(static_cast<bool>(opt2) == true); 162 assert(*opt2 == 1); 163 } 164 { 165 optional<X> opt1; 166 optional<X> opt2; 167 static_assert(noexcept(swap(opt1, opt2)) == true, ""); 168 assert(static_cast<bool>(opt1) == false); 169 assert(static_cast<bool>(opt2) == false); 170 swap(opt1, opt2); 171 assert(static_cast<bool>(opt1) == false); 172 assert(static_cast<bool>(opt2) == false); 173 assert(X::dtor_called == 0); 174 } 175 { 176 optional<X> opt1(1); 177 optional<X> opt2; 178 static_assert(noexcept(swap(opt1, opt2)) == true, ""); 179 assert(static_cast<bool>(opt1) == true); 180 assert(*opt1 == 1); 181 assert(static_cast<bool>(opt2) == false); 182 X::dtor_called = 0; 183 swap(opt1, opt2); 184 assert(X::dtor_called == 1); 185 assert(static_cast<bool>(opt1) == false); 186 assert(static_cast<bool>(opt2) == true); 187 assert(*opt2 == 1); 188 } 189 { 190 optional<X> opt1; 191 optional<X> opt2(2); 192 static_assert(noexcept(swap(opt1, opt2)) == true, ""); 193 assert(static_cast<bool>(opt1) == false); 194 assert(static_cast<bool>(opt2) == true); 195 assert(*opt2 == 2); 196 X::dtor_called = 0; 197 swap(opt1, opt2); 198 assert(X::dtor_called == 1); 199 assert(static_cast<bool>(opt1) == true); 200 assert(*opt1 == 2); 201 assert(static_cast<bool>(opt2) == false); 202 } 203 { 204 optional<X> opt1(1); 205 optional<X> opt2(2); 206 static_assert(noexcept(swap(opt1, opt2)) == true, ""); 207 assert(static_cast<bool>(opt1) == true); 208 assert(*opt1 == 1); 209 assert(static_cast<bool>(opt2) == true); 210 assert(*opt2 == 2); 211 X::dtor_called = 0; 212 swap(opt1, opt2); 213 assert(X::dtor_called == 1); // from inside std::swap 214 assert(static_cast<bool>(opt1) == true); 215 assert(*opt1 == 2); 216 assert(static_cast<bool>(opt2) == true); 217 assert(*opt2 == 1); 218 } 219 { 220 optional<Y> opt1; 221 optional<Y> opt2; 222 static_assert(noexcept(swap(opt1, opt2)) == false, ""); 223 assert(static_cast<bool>(opt1) == false); 224 assert(static_cast<bool>(opt2) == false); 225 swap(opt1, opt2); 226 assert(static_cast<bool>(opt1) == false); 227 assert(static_cast<bool>(opt2) == false); 228 assert(Y::dtor_called == 0); 229 } 230 { 231 optional<Y> opt1(1); 232 optional<Y> opt2; 233 static_assert(noexcept(swap(opt1, opt2)) == false, ""); 234 assert(static_cast<bool>(opt1) == true); 235 assert(*opt1 == 1); 236 assert(static_cast<bool>(opt2) == false); 237 Y::dtor_called = 0; 238 swap(opt1, opt2); 239 assert(Y::dtor_called == 1); 240 assert(static_cast<bool>(opt1) == false); 241 assert(static_cast<bool>(opt2) == true); 242 assert(*opt2 == 1); 243 } 244 { 245 optional<Y> opt1; 246 optional<Y> opt2(2); 247 static_assert(noexcept(swap(opt1, opt2)) == false, ""); 248 assert(static_cast<bool>(opt1) == false); 249 assert(static_cast<bool>(opt2) == true); 250 assert(*opt2 == 2); 251 Y::dtor_called = 0; 252 swap(opt1, opt2); 253 assert(Y::dtor_called == 1); 254 assert(static_cast<bool>(opt1) == true); 255 assert(*opt1 == 2); 256 assert(static_cast<bool>(opt2) == false); 257 } 258 { 259 optional<Y> opt1(1); 260 optional<Y> opt2(2); 261 static_assert(noexcept(swap(opt1, opt2)) == false, ""); 262 assert(static_cast<bool>(opt1) == true); 263 assert(*opt1 == 1); 264 assert(static_cast<bool>(opt2) == true); 265 assert(*opt2 == 2); 266 Y::dtor_called = 0; 267 swap(opt1, opt2); 268 assert(Y::dtor_called == 0); 269 assert(static_cast<bool>(opt1) == true); 270 assert(*opt1 == 2); 271 assert(static_cast<bool>(opt2) == true); 272 assert(*opt2 == 1); 273 } 274 { 275 optional<Z> opt1; 276 optional<Z> opt2; 277 static_assert(noexcept(swap(opt1, opt2)) == false, ""); 278 assert(static_cast<bool>(opt1) == false); 279 assert(static_cast<bool>(opt2) == false); 280 swap(opt1, opt2); 281 assert(static_cast<bool>(opt1) == false); 282 assert(static_cast<bool>(opt2) == false); 283 } 284 #ifndef TEST_HAS_NO_EXCEPTIONS 285 { 286 optional<Z> opt1; 287 opt1.emplace(1); 288 optional<Z> opt2; 289 static_assert(noexcept(swap(opt1, opt2)) == false, ""); 290 assert(static_cast<bool>(opt1) == true); 291 assert(*opt1 == 1); 292 assert(static_cast<bool>(opt2) == false); 293 try 294 { 295 swap(opt1, opt2); 296 assert(false); 297 } 298 catch (int i) 299 { 300 assert(i == 7); 301 } 302 assert(static_cast<bool>(opt1) == true); 303 assert(*opt1 == 1); 304 assert(static_cast<bool>(opt2) == false); 305 } 306 { 307 optional<Z> opt1; 308 optional<Z> opt2; 309 opt2.emplace(2); 310 static_assert(noexcept(swap(opt1, opt2)) == false, ""); 311 assert(static_cast<bool>(opt1) == false); 312 assert(static_cast<bool>(opt2) == true); 313 assert(*opt2 == 2); 314 try 315 { 316 swap(opt1, opt2); 317 assert(false); 318 } 319 catch (int i) 320 { 321 assert(i == 7); 322 } 323 assert(static_cast<bool>(opt1) == false); 324 assert(static_cast<bool>(opt2) == true); 325 assert(*opt2 == 2); 326 } 327 { 328 optional<Z> opt1; 329 opt1.emplace(1); 330 optional<Z> opt2; 331 opt2.emplace(2); 332 static_assert(noexcept(swap(opt1, opt2)) == false, ""); 333 assert(static_cast<bool>(opt1) == true); 334 assert(*opt1 == 1); 335 assert(static_cast<bool>(opt2) == true); 336 assert(*opt2 == 2); 337 try 338 { 339 swap(opt1, opt2); 340 assert(false); 341 } 342 catch (int i) 343 { 344 assert(i == 6); 345 } 346 assert(static_cast<bool>(opt1) == true); 347 assert(*opt1 == 1); 348 assert(static_cast<bool>(opt2) == true); 349 assert(*opt2 == 2); 350 } 351 #endif // TEST_HAS_NO_EXCEPTIONS 352 } 353