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