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 10 // <optional> 11 12 // void swap(optional&) 13 // noexcept(is_nothrow_move_constructible<T>::value && 14 // is_nothrow_swappable<T>::value) 15 16 #include <optional> 17 #include <type_traits> 18 #include <cassert> 19 20 #include "test_macros.h" 21 #include "archetypes.h" 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 class W 67 { 68 int i_; 69 public: 70 constexpr W(int i) : i_(i) {} 71 72 friend constexpr bool operator==(const W& x, const W& y) {return x.i_ == y.i_;} 73 friend TEST_CONSTEXPR_CXX20 void swap(W& x, W& y) noexcept {std::swap(x.i_, y.i_);} 74 }; 75 76 template<class T> 77 TEST_CONSTEXPR_CXX20 bool check_swap() 78 { 79 { 80 optional<T> opt1; 81 optional<T> opt2; 82 static_assert(noexcept(opt1.swap(opt2)) == true); 83 assert(static_cast<bool>(opt1) == false); 84 assert(static_cast<bool>(opt2) == false); 85 opt1.swap(opt2); 86 assert(static_cast<bool>(opt1) == false); 87 assert(static_cast<bool>(opt2) == false); 88 } 89 { 90 optional<T> opt1(1); 91 optional<T> opt2; 92 static_assert(noexcept(opt1.swap(opt2)) == true); 93 assert(static_cast<bool>(opt1) == true); 94 assert(*opt1 == 1); 95 assert(static_cast<bool>(opt2) == false); 96 opt1.swap(opt2); 97 assert(static_cast<bool>(opt1) == false); 98 assert(static_cast<bool>(opt2) == true); 99 assert(*opt2 == 1); 100 } 101 { 102 optional<T> opt1; 103 optional<T> opt2(2); 104 static_assert(noexcept(opt1.swap(opt2)) == true, ""); 105 assert(static_cast<bool>(opt1) == false); 106 assert(static_cast<bool>(opt2) == true); 107 assert(*opt2 == 2); 108 opt1.swap(opt2); 109 assert(static_cast<bool>(opt1) == true); 110 assert(*opt1 == 2); 111 assert(static_cast<bool>(opt2) == false); 112 } 113 { 114 optional<T> opt1(1); 115 optional<T> opt2(2); 116 static_assert(noexcept(opt1.swap(opt2)) == true, ""); 117 assert(static_cast<bool>(opt1) == true); 118 assert(*opt1 == 1); 119 assert(static_cast<bool>(opt2) == true); 120 assert(*opt2 == 2); 121 opt1.swap(opt2); 122 assert(static_cast<bool>(opt1) == true); 123 assert(*opt1 == 2); 124 assert(static_cast<bool>(opt2) == true); 125 assert(*opt2 == 1); 126 } 127 return true; 128 } 129 130 int main(int, char**) 131 { 132 check_swap<int>(); 133 check_swap<W>(); 134 #if TEST_STD_VER > 17 135 static_assert(check_swap<int>()); 136 static_assert(check_swap<W>()); 137 #endif 138 { 139 optional<X> opt1; 140 optional<X> opt2; 141 static_assert(noexcept(opt1.swap(opt2)) == true, ""); 142 assert(static_cast<bool>(opt1) == false); 143 assert(static_cast<bool>(opt2) == false); 144 opt1.swap(opt2); 145 assert(static_cast<bool>(opt1) == false); 146 assert(static_cast<bool>(opt2) == false); 147 assert(X::dtor_called == 0); 148 } 149 { 150 optional<X> opt1(1); 151 optional<X> opt2; 152 static_assert(noexcept(opt1.swap(opt2)) == true, ""); 153 assert(static_cast<bool>(opt1) == true); 154 assert(*opt1 == 1); 155 assert(static_cast<bool>(opt2) == false); 156 X::dtor_called = 0; 157 opt1.swap(opt2); 158 assert(X::dtor_called == 1); 159 assert(static_cast<bool>(opt1) == false); 160 assert(static_cast<bool>(opt2) == true); 161 assert(*opt2 == 1); 162 } 163 { 164 optional<X> opt1; 165 optional<X> opt2(2); 166 static_assert(noexcept(opt1.swap(opt2)) == true, ""); 167 assert(static_cast<bool>(opt1) == false); 168 assert(static_cast<bool>(opt2) == true); 169 assert(*opt2 == 2); 170 X::dtor_called = 0; 171 opt1.swap(opt2); 172 assert(X::dtor_called == 1); 173 assert(static_cast<bool>(opt1) == true); 174 assert(*opt1 == 2); 175 assert(static_cast<bool>(opt2) == false); 176 } 177 { 178 optional<X> opt1(1); 179 optional<X> opt2(2); 180 static_assert(noexcept(opt1.swap(opt2)) == true, ""); 181 assert(static_cast<bool>(opt1) == true); 182 assert(*opt1 == 1); 183 assert(static_cast<bool>(opt2) == true); 184 assert(*opt2 == 2); 185 X::dtor_called = 0; 186 opt1.swap(opt2); 187 assert(X::dtor_called == 1); // from inside std::swap 188 assert(static_cast<bool>(opt1) == true); 189 assert(*opt1 == 2); 190 assert(static_cast<bool>(opt2) == true); 191 assert(*opt2 == 1); 192 } 193 { 194 optional<Y> opt1; 195 optional<Y> opt2; 196 static_assert(noexcept(opt1.swap(opt2)) == false, ""); 197 assert(static_cast<bool>(opt1) == false); 198 assert(static_cast<bool>(opt2) == false); 199 opt1.swap(opt2); 200 assert(static_cast<bool>(opt1) == false); 201 assert(static_cast<bool>(opt2) == false); 202 assert(Y::dtor_called == 0); 203 } 204 { 205 optional<Y> opt1(1); 206 optional<Y> opt2; 207 static_assert(noexcept(opt1.swap(opt2)) == false, ""); 208 assert(static_cast<bool>(opt1) == true); 209 assert(*opt1 == 1); 210 assert(static_cast<bool>(opt2) == false); 211 Y::dtor_called = 0; 212 opt1.swap(opt2); 213 assert(Y::dtor_called == 1); 214 assert(static_cast<bool>(opt1) == false); 215 assert(static_cast<bool>(opt2) == true); 216 assert(*opt2 == 1); 217 } 218 { 219 optional<Y> opt1; 220 optional<Y> opt2(2); 221 static_assert(noexcept(opt1.swap(opt2)) == false, ""); 222 assert(static_cast<bool>(opt1) == false); 223 assert(static_cast<bool>(opt2) == true); 224 assert(*opt2 == 2); 225 Y::dtor_called = 0; 226 opt1.swap(opt2); 227 assert(Y::dtor_called == 1); 228 assert(static_cast<bool>(opt1) == true); 229 assert(*opt1 == 2); 230 assert(static_cast<bool>(opt2) == false); 231 } 232 { 233 optional<Y> opt1(1); 234 optional<Y> opt2(2); 235 static_assert(noexcept(opt1.swap(opt2)) == false, ""); 236 assert(static_cast<bool>(opt1) == true); 237 assert(*opt1 == 1); 238 assert(static_cast<bool>(opt2) == true); 239 assert(*opt2 == 2); 240 Y::dtor_called = 0; 241 opt1.swap(opt2); 242 assert(Y::dtor_called == 0); 243 assert(static_cast<bool>(opt1) == true); 244 assert(*opt1 == 2); 245 assert(static_cast<bool>(opt2) == true); 246 assert(*opt2 == 1); 247 } 248 { 249 optional<Z> opt1; 250 optional<Z> opt2; 251 static_assert(noexcept(opt1.swap(opt2)) == false, ""); 252 assert(static_cast<bool>(opt1) == false); 253 assert(static_cast<bool>(opt2) == false); 254 opt1.swap(opt2); 255 assert(static_cast<bool>(opt1) == false); 256 assert(static_cast<bool>(opt2) == false); 257 } 258 #ifndef TEST_HAS_NO_EXCEPTIONS 259 { 260 optional<Z> opt1; 261 opt1.emplace(1); 262 optional<Z> opt2; 263 static_assert(noexcept(opt1.swap(opt2)) == false, ""); 264 assert(static_cast<bool>(opt1) == true); 265 assert(*opt1 == 1); 266 assert(static_cast<bool>(opt2) == false); 267 try 268 { 269 opt1.swap(opt2); 270 assert(false); 271 } 272 catch (int i) 273 { 274 assert(i == 7); 275 } 276 assert(static_cast<bool>(opt1) == true); 277 assert(*opt1 == 1); 278 assert(static_cast<bool>(opt2) == false); 279 } 280 { 281 optional<Z> opt1; 282 optional<Z> opt2; 283 opt2.emplace(2); 284 static_assert(noexcept(opt1.swap(opt2)) == false, ""); 285 assert(static_cast<bool>(opt1) == false); 286 assert(static_cast<bool>(opt2) == true); 287 assert(*opt2 == 2); 288 try 289 { 290 opt1.swap(opt2); 291 assert(false); 292 } 293 catch (int i) 294 { 295 assert(i == 7); 296 } 297 assert(static_cast<bool>(opt1) == false); 298 assert(static_cast<bool>(opt2) == true); 299 assert(*opt2 == 2); 300 } 301 { 302 optional<Z> opt1; 303 opt1.emplace(1); 304 optional<Z> opt2; 305 opt2.emplace(2); 306 static_assert(noexcept(opt1.swap(opt2)) == false, ""); 307 assert(static_cast<bool>(opt1) == true); 308 assert(*opt1 == 1); 309 assert(static_cast<bool>(opt2) == true); 310 assert(*opt2 == 2); 311 try 312 { 313 opt1.swap(opt2); 314 assert(false); 315 } 316 catch (int i) 317 { 318 assert(i == 6); 319 } 320 assert(static_cast<bool>(opt1) == true); 321 assert(*opt1 == 1); 322 assert(static_cast<bool>(opt2) == true); 323 assert(*opt2 == 2); 324 } 325 #endif 326 327 return 0; 328 } 329