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