404 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// void swap(optional&)13// noexcept(is_nothrow_move_constructible<T>::value &&14// is_nothrow_swappable<T>::value)15 16#include <cassert>17#include <memory>18#include <optional>19#include <type_traits>20 21#include "test_macros.h"22#include "archetypes.h"23 24using std::optional;25 26class X27{28 int i_;29public: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 39unsigned X::dtor_called = 0;40 41class Y42{43 int i_;44public: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 54unsigned Y::dtor_called = 0;55 56class Z57{58 int i_;59public: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 67class W68{69 int i_;70public: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 77template<class T>78TEST_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#if TEST_STD_VER >= 26132template <typename T>133constexpr bool check_swap_ref() {134 {135 optional<T&> opt1;136 optional<T&> opt2;137 static_assert(noexcept(opt1.swap(opt2)) == true);138 assert(static_cast<bool>(opt1) == false);139 assert(static_cast<bool>(opt2) == false);140 opt1.swap(opt2);141 assert(static_cast<bool>(opt1) == false);142 assert(static_cast<bool>(opt2) == false);143 }144 145 {146 T one{1};147 optional<T&> opt1(one);148 optional<T&> opt2;149 static_assert(noexcept(opt1.swap(opt2)) == true);150 assert(static_cast<bool>(opt1) == true);151 assert(std::addressof(*opt1) == std::addressof(one));152 assert(static_cast<bool>(opt2) == false);153 opt1.swap(opt2);154 assert(static_cast<bool>(opt1) == false);155 assert(static_cast<bool>(opt2) == true);156 assert(std::addressof(*opt2) == std::addressof(one));157 }158 159 {160 T two{2};161 optional<T&> opt1;162 optional<T&> opt2(two);163 static_assert(noexcept(opt1.swap(opt2)) == true);164 assert(static_cast<bool>(opt1) == false);165 assert(static_cast<bool>(opt2) == true);166 assert(std::addressof(*opt2) == std::addressof(two));167 opt1.swap(opt2);168 assert(static_cast<bool>(opt1) == true);169 assert(std::addressof(*opt1) == std::addressof(two));170 assert(static_cast<bool>(opt2) == false);171 }172 173 {174 T one{1};175 T two{2};176 177 optional<T&> opt1(one);178 optional<T&> opt2(two);179 static_assert(noexcept(opt1.swap(opt2)) == true);180 assert(static_cast<bool>(opt1) == true);181 assert(*opt1 == 1);182 assert(std::addressof(*opt1) == std::addressof(one));183 assert(static_cast<bool>(opt2) == true);184 assert(*opt2 == 2);185 assert(std::addressof(*opt2) == std::addressof(two));186 opt1.swap(opt2);187 assert(static_cast<bool>(opt1) == true);188 assert(*opt1 == 2);189 assert(std::addressof(*opt1) == std::addressof(two));190 assert(static_cast<bool>(opt2) == true);191 assert(*opt2 == 1);192 assert(std::addressof(*opt2) == std::addressof(one));193 }194 195 return true;196}197#endif198 199int main(int, char**)200{201 check_swap<int>();202 check_swap<W>();203#if TEST_STD_VER > 17204 static_assert(check_swap<int>());205 static_assert(check_swap<W>());206#endif207#if TEST_STD_VER >= 26208 static_assert(check_swap_ref<int>());209 static_assert(check_swap_ref<W>());210 check_swap_ref<int>();211 check_swap_ref<W>();212#endif213 {214 optional<X> opt1;215 optional<X> opt2;216 static_assert(noexcept(opt1.swap(opt2)) == true, "");217 assert(static_cast<bool>(opt1) == false);218 assert(static_cast<bool>(opt2) == false);219 opt1.swap(opt2);220 assert(static_cast<bool>(opt1) == false);221 assert(static_cast<bool>(opt2) == false);222 assert(X::dtor_called == 0);223 }224 {225 optional<X> opt1(1);226 optional<X> opt2;227 static_assert(noexcept(opt1.swap(opt2)) == true, "");228 assert(static_cast<bool>(opt1) == true);229 assert(*opt1 == 1);230 assert(static_cast<bool>(opt2) == false);231 X::dtor_called = 0;232 opt1.swap(opt2);233 assert(X::dtor_called == 1);234 assert(static_cast<bool>(opt1) == false);235 assert(static_cast<bool>(opt2) == true);236 assert(*opt2 == 1);237 }238 {239 optional<X> opt1;240 optional<X> opt2(2);241 static_assert(noexcept(opt1.swap(opt2)) == true, "");242 assert(static_cast<bool>(opt1) == false);243 assert(static_cast<bool>(opt2) == true);244 assert(*opt2 == 2);245 X::dtor_called = 0;246 opt1.swap(opt2);247 assert(X::dtor_called == 1);248 assert(static_cast<bool>(opt1) == true);249 assert(*opt1 == 2);250 assert(static_cast<bool>(opt2) == false);251 }252 {253 optional<X> opt1(1);254 optional<X> opt2(2);255 static_assert(noexcept(opt1.swap(opt2)) == true, "");256 assert(static_cast<bool>(opt1) == true);257 assert(*opt1 == 1);258 assert(static_cast<bool>(opt2) == true);259 assert(*opt2 == 2);260 X::dtor_called = 0;261 opt1.swap(opt2);262 assert(X::dtor_called == 1); // from inside std::swap263 assert(static_cast<bool>(opt1) == true);264 assert(*opt1 == 2);265 assert(static_cast<bool>(opt2) == true);266 assert(*opt2 == 1);267 }268 {269 optional<Y> opt1;270 optional<Y> opt2;271 static_assert(noexcept(opt1.swap(opt2)) == false, "");272 assert(static_cast<bool>(opt1) == false);273 assert(static_cast<bool>(opt2) == false);274 opt1.swap(opt2);275 assert(static_cast<bool>(opt1) == false);276 assert(static_cast<bool>(opt2) == false);277 assert(Y::dtor_called == 0);278 }279 {280 optional<Y> opt1(1);281 optional<Y> opt2;282 static_assert(noexcept(opt1.swap(opt2)) == false, "");283 assert(static_cast<bool>(opt1) == true);284 assert(*opt1 == 1);285 assert(static_cast<bool>(opt2) == false);286 Y::dtor_called = 0;287 opt1.swap(opt2);288 assert(Y::dtor_called == 1);289 assert(static_cast<bool>(opt1) == false);290 assert(static_cast<bool>(opt2) == true);291 assert(*opt2 == 1);292 }293 {294 optional<Y> opt1;295 optional<Y> opt2(2);296 static_assert(noexcept(opt1.swap(opt2)) == false, "");297 assert(static_cast<bool>(opt1) == false);298 assert(static_cast<bool>(opt2) == true);299 assert(*opt2 == 2);300 Y::dtor_called = 0;301 opt1.swap(opt2);302 assert(Y::dtor_called == 1);303 assert(static_cast<bool>(opt1) == true);304 assert(*opt1 == 2);305 assert(static_cast<bool>(opt2) == false);306 }307 {308 optional<Y> opt1(1);309 optional<Y> opt2(2);310 static_assert(noexcept(opt1.swap(opt2)) == false, "");311 assert(static_cast<bool>(opt1) == true);312 assert(*opt1 == 1);313 assert(static_cast<bool>(opt2) == true);314 assert(*opt2 == 2);315 Y::dtor_called = 0;316 opt1.swap(opt2);317 assert(Y::dtor_called == 0);318 assert(static_cast<bool>(opt1) == true);319 assert(*opt1 == 2);320 assert(static_cast<bool>(opt2) == true);321 assert(*opt2 == 1);322 }323 {324 optional<Z> opt1;325 optional<Z> opt2;326 static_assert(noexcept(opt1.swap(opt2)) == false, "");327 assert(static_cast<bool>(opt1) == false);328 assert(static_cast<bool>(opt2) == false);329 opt1.swap(opt2);330 assert(static_cast<bool>(opt1) == false);331 assert(static_cast<bool>(opt2) == false);332 }333#ifndef TEST_HAS_NO_EXCEPTIONS334 {335 optional<Z> opt1;336 opt1.emplace(1);337 optional<Z> opt2;338 static_assert(noexcept(opt1.swap(opt2)) == false, "");339 assert(static_cast<bool>(opt1) == true);340 assert(*opt1 == 1);341 assert(static_cast<bool>(opt2) == false);342 try343 {344 opt1.swap(opt2);345 assert(false);346 }347 catch (int i)348 {349 assert(i == 7);350 }351 assert(static_cast<bool>(opt1) == true);352 assert(*opt1 == 1);353 assert(static_cast<bool>(opt2) == false);354 }355 {356 optional<Z> opt1;357 optional<Z> opt2;358 opt2.emplace(2);359 static_assert(noexcept(opt1.swap(opt2)) == false, "");360 assert(static_cast<bool>(opt1) == false);361 assert(static_cast<bool>(opt2) == true);362 assert(*opt2 == 2);363 try364 {365 opt1.swap(opt2);366 assert(false);367 }368 catch (int i)369 {370 assert(i == 7);371 }372 assert(static_cast<bool>(opt1) == false);373 assert(static_cast<bool>(opt2) == true);374 assert(*opt2 == 2);375 }376 {377 optional<Z> opt1;378 opt1.emplace(1);379 optional<Z> opt2;380 opt2.emplace(2);381 static_assert(noexcept(opt1.swap(opt2)) == false, "");382 assert(static_cast<bool>(opt1) == true);383 assert(*opt1 == 1);384 assert(static_cast<bool>(opt2) == true);385 assert(*opt2 == 2);386 try387 {388 opt1.swap(opt2);389 assert(false);390 }391 catch (int i)392 {393 assert(i == 6);394 }395 assert(static_cast<bool>(opt1) == true);396 assert(*opt1 == 1);397 assert(static_cast<bool>(opt2) == true);398 assert(*opt2 == 2);399 }400#endif401 402 return 0;403}404