428 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++1410// <optional>11 12// template <class T> void swap(optional<T>& x, optional<T>& y)13// noexcept(noexcept(x.swap(y)));14 15#include <cassert>16#include <memory>17#include <optional>18#include <type_traits>19 20#include "test_macros.h"21#include "archetypes.h"22 23using std::optional;24 25class X26{27 int i_;28public: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 38unsigned X::dtor_called = 0;39 40class Y41{42 int i_;43public: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 53unsigned Y::dtor_called = 0;54 55class Z56{57 int i_;58public: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 67struct NonSwappable {68 NonSwappable(NonSwappable const&) = delete;69};70void swap(NonSwappable&, NonSwappable&) = delete;71 72void 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 though CopyOnly has deleted move operations, those operations96 // cause optional<CopyOnly> to have implicitly deleted move operations97 // 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#if TEST_STD_VER >= 26114template <typename T>115constexpr bool test_swap_ref() {116 {117 optional<T&> opt1;118 optional<T&> 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 T one{1};128 optional<T&> opt1(one);129 optional<T&> opt2;130 static_assert(noexcept(swap(opt1, opt2)) == true);131 assert(static_cast<bool>(opt1) == true);132 assert(*opt1 == 1);133 assert(std::addressof(*opt1) == std::addressof(one));134 assert(static_cast<bool>(opt2) == false);135 swap(opt1, opt2);136 assert(static_cast<bool>(opt1) == false);137 assert(static_cast<bool>(opt2) == true);138 assert(*opt2 == 1);139 assert(std::addressof(*opt2) == std::addressof(one));140 }141 {142 T two{2};143 optional<T&> opt1;144 optional<T&> opt2(two);145 static_assert(noexcept(swap(opt1, opt2)) == true);146 assert(static_cast<bool>(opt1) == false);147 assert(static_cast<bool>(opt2) == true);148 assert(*opt2 == 2);149 assert(std::addressof(*opt2) == std::addressof(two));150 swap(opt1, opt2);151 assert(static_cast<bool>(opt1) == true);152 assert(*opt1 == 2);153 assert(std::addressof(*opt1) == std::addressof(two));154 assert(static_cast<bool>(opt2) == false);155 }156 {157 T one{1};158 T two{2};159 optional<T&> opt1(one);160 optional<T&> opt2(two);161 static_assert(noexcept(swap(opt1, opt2)) == true);162 assert(static_cast<bool>(opt1) == true);163 assert(*opt1 == 1);164 assert(std::addressof(*opt1) == std::addressof(one));165 assert(static_cast<bool>(opt2) == true);166 assert(*opt2 == 2);167 assert(std::addressof(*opt2) == std::addressof(two));168 swap(opt1, opt2);169 assert(static_cast<bool>(opt1) == true);170 assert(*opt1 == 2);171 assert(std::addressof(*opt1) == std::addressof(two));172 assert(static_cast<bool>(opt2) == true);173 assert(*opt2 == 1);174 assert(std::addressof(*opt2) == std::addressof(one));175 }176 return true;177}178#endif179 180int main(int, char**)181{182 test_swap_sfinae();183#if TEST_STD_VER >= 26184 static_assert(test_swap_ref<int>());185 static_assert(test_swap_ref<double>());186 test_swap_ref<int>();187 test_swap_ref<double>();188#endif189 {190 optional<int> opt1;191 optional<int> opt2;192 static_assert(noexcept(swap(opt1, opt2)) == true, "");193 assert(static_cast<bool>(opt1) == false);194 assert(static_cast<bool>(opt2) == false);195 swap(opt1, opt2);196 assert(static_cast<bool>(opt1) == false);197 assert(static_cast<bool>(opt2) == false);198 }199 {200 optional<int> opt1(1);201 optional<int> opt2;202 static_assert(noexcept(swap(opt1, opt2)) == true, "");203 assert(static_cast<bool>(opt1) == true);204 assert(*opt1 == 1);205 assert(static_cast<bool>(opt2) == false);206 swap(opt1, opt2);207 assert(static_cast<bool>(opt1) == false);208 assert(static_cast<bool>(opt2) == true);209 assert(*opt2 == 1);210 }211 {212 optional<int> opt1;213 optional<int> opt2(2);214 static_assert(noexcept(swap(opt1, opt2)) == true, "");215 assert(static_cast<bool>(opt1) == false);216 assert(static_cast<bool>(opt2) == true);217 assert(*opt2 == 2);218 swap(opt1, opt2);219 assert(static_cast<bool>(opt1) == true);220 assert(*opt1 == 2);221 assert(static_cast<bool>(opt2) == false);222 }223 {224 optional<int> opt1(1);225 optional<int> opt2(2);226 static_assert(noexcept(swap(opt1, opt2)) == true, "");227 assert(static_cast<bool>(opt1) == true);228 assert(*opt1 == 1);229 assert(static_cast<bool>(opt2) == true);230 assert(*opt2 == 2);231 swap(opt1, opt2);232 assert(static_cast<bool>(opt1) == true);233 assert(*opt1 == 2);234 assert(static_cast<bool>(opt2) == true);235 assert(*opt2 == 1);236 }237 {238 optional<X> opt1;239 optional<X> opt2;240 static_assert(noexcept(swap(opt1, opt2)) == true, "");241 assert(static_cast<bool>(opt1) == false);242 assert(static_cast<bool>(opt2) == false);243 swap(opt1, opt2);244 assert(static_cast<bool>(opt1) == false);245 assert(static_cast<bool>(opt2) == false);246 assert(X::dtor_called == 0);247 }248 {249 optional<X> opt1(1);250 optional<X> opt2;251 static_assert(noexcept(swap(opt1, opt2)) == true, "");252 assert(static_cast<bool>(opt1) == true);253 assert(*opt1 == 1);254 assert(static_cast<bool>(opt2) == false);255 X::dtor_called = 0;256 swap(opt1, opt2);257 assert(X::dtor_called == 1);258 assert(static_cast<bool>(opt1) == false);259 assert(static_cast<bool>(opt2) == true);260 assert(*opt2 == 1);261 }262 {263 optional<X> opt1;264 optional<X> opt2(2);265 static_assert(noexcept(swap(opt1, opt2)) == true, "");266 assert(static_cast<bool>(opt1) == false);267 assert(static_cast<bool>(opt2) == true);268 assert(*opt2 == 2);269 X::dtor_called = 0;270 swap(opt1, opt2);271 assert(X::dtor_called == 1);272 assert(static_cast<bool>(opt1) == true);273 assert(*opt1 == 2);274 assert(static_cast<bool>(opt2) == false);275 }276 {277 optional<X> opt1(1);278 optional<X> opt2(2);279 static_assert(noexcept(swap(opt1, opt2)) == true, "");280 assert(static_cast<bool>(opt1) == true);281 assert(*opt1 == 1);282 assert(static_cast<bool>(opt2) == true);283 assert(*opt2 == 2);284 X::dtor_called = 0;285 swap(opt1, opt2);286 assert(X::dtor_called == 1); // from inside std::swap287 assert(static_cast<bool>(opt1) == true);288 assert(*opt1 == 2);289 assert(static_cast<bool>(opt2) == true);290 assert(*opt2 == 1);291 }292 {293 optional<Y> opt1;294 optional<Y> opt2;295 static_assert(noexcept(swap(opt1, opt2)) == false, "");296 assert(static_cast<bool>(opt1) == false);297 assert(static_cast<bool>(opt2) == false);298 swap(opt1, opt2);299 assert(static_cast<bool>(opt1) == false);300 assert(static_cast<bool>(opt2) == false);301 assert(Y::dtor_called == 0);302 }303 {304 optional<Y> opt1(1);305 optional<Y> opt2;306 static_assert(noexcept(swap(opt1, opt2)) == false, "");307 assert(static_cast<bool>(opt1) == true);308 assert(*opt1 == 1);309 assert(static_cast<bool>(opt2) == false);310 Y::dtor_called = 0;311 swap(opt1, opt2);312 assert(Y::dtor_called == 1);313 assert(static_cast<bool>(opt1) == false);314 assert(static_cast<bool>(opt2) == true);315 assert(*opt2 == 1);316 }317 {318 optional<Y> opt1;319 optional<Y> opt2(2);320 static_assert(noexcept(swap(opt1, opt2)) == false, "");321 assert(static_cast<bool>(opt1) == false);322 assert(static_cast<bool>(opt2) == true);323 assert(*opt2 == 2);324 Y::dtor_called = 0;325 swap(opt1, opt2);326 assert(Y::dtor_called == 1);327 assert(static_cast<bool>(opt1) == true);328 assert(*opt1 == 2);329 assert(static_cast<bool>(opt2) == false);330 }331 {332 optional<Y> opt1(1);333 optional<Y> opt2(2);334 static_assert(noexcept(swap(opt1, opt2)) == false, "");335 assert(static_cast<bool>(opt1) == true);336 assert(*opt1 == 1);337 assert(static_cast<bool>(opt2) == true);338 assert(*opt2 == 2);339 Y::dtor_called = 0;340 swap(opt1, opt2);341 assert(Y::dtor_called == 0);342 assert(static_cast<bool>(opt1) == true);343 assert(*opt1 == 2);344 assert(static_cast<bool>(opt2) == true);345 assert(*opt2 == 1);346 }347 {348 optional<Z> opt1;349 optional<Z> opt2;350 static_assert(noexcept(swap(opt1, opt2)) == false, "");351 assert(static_cast<bool>(opt1) == false);352 assert(static_cast<bool>(opt2) == false);353 swap(opt1, opt2);354 assert(static_cast<bool>(opt1) == false);355 assert(static_cast<bool>(opt2) == false);356 }357#ifndef TEST_HAS_NO_EXCEPTIONS358 {359 optional<Z> opt1;360 opt1.emplace(1);361 optional<Z> opt2;362 static_assert(noexcept(swap(opt1, opt2)) == false, "");363 assert(static_cast<bool>(opt1) == true);364 assert(*opt1 == 1);365 assert(static_cast<bool>(opt2) == false);366 try367 {368 swap(opt1, opt2);369 assert(false);370 }371 catch (int i)372 {373 assert(i == 7);374 }375 assert(static_cast<bool>(opt1) == true);376 assert(*opt1 == 1);377 assert(static_cast<bool>(opt2) == false);378 }379 {380 optional<Z> opt1;381 optional<Z> opt2;382 opt2.emplace(2);383 static_assert(noexcept(swap(opt1, opt2)) == false, "");384 assert(static_cast<bool>(opt1) == false);385 assert(static_cast<bool>(opt2) == true);386 assert(*opt2 == 2);387 try388 {389 swap(opt1, opt2);390 assert(false);391 }392 catch (int i)393 {394 assert(i == 7);395 }396 assert(static_cast<bool>(opt1) == false);397 assert(static_cast<bool>(opt2) == true);398 assert(*opt2 == 2);399 }400 {401 optional<Z> opt1;402 opt1.emplace(1);403 optional<Z> opt2;404 opt2.emplace(2);405 static_assert(noexcept(swap(opt1, opt2)) == false, "");406 assert(static_cast<bool>(opt1) == true);407 assert(*opt1 == 1);408 assert(static_cast<bool>(opt2) == true);409 assert(*opt2 == 2);410 try411 {412 swap(opt1, opt2);413 assert(false);414 }415 catch (int i)416 {417 assert(i == 6);418 }419 assert(static_cast<bool>(opt1) == true);420 assert(*opt1 == 1);421 assert(static_cast<bool>(opt2) == true);422 assert(*opt2 == 2);423 }424#endif // TEST_HAS_NO_EXCEPTIONS425 426 return 0;427}428