Home | History | Annotate | Download | only in optional.specalg
      1 //===----------------------------------------------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is dual licensed under the MIT and the University of Illinois Open
      6 // Source Licenses. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 // UNSUPPORTED: c++98, c++03, c++11, c++14
     11 // <optional>
     12 
     13 // template <class T> void swap(optional<T>& x, optional<T>& y)
     14 //     noexcept(noexcept(x.swap(y)));
     15 
     16 #include <optional>
     17 #include <type_traits>
     18 #include <cassert>
     19 
     20 #include "test_macros.h"
     21 #include "archetypes.hpp"
     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 
     67 struct NonSwappable {
     68     NonSwappable(NonSwappable const&) = delete;
     69 };
     70 void swap(NonSwappable&, NonSwappable&) = delete;
     71 
     72 void 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 thought CopyOnly has deleted move operations, those operations
     96         // cause optional<CopyOnly> to have implicitly deleted move operations
     97         // 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 int main()
    114 {
    115     test_swap_sfinae();
    116     {
    117         optional<int> opt1;
    118         optional<int> 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         optional<int> opt1(1);
    128         optional<int> opt2;
    129         static_assert(noexcept(swap(opt1, opt2)) == true, "");
    130         assert(static_cast<bool>(opt1) == true);
    131         assert(*opt1 == 1);
    132         assert(static_cast<bool>(opt2) == false);
    133         swap(opt1, opt2);
    134         assert(static_cast<bool>(opt1) == false);
    135         assert(static_cast<bool>(opt2) == true);
    136         assert(*opt2 == 1);
    137     }
    138     {
    139         optional<int> opt1;
    140         optional<int> opt2(2);
    141         static_assert(noexcept(swap(opt1, opt2)) == true, "");
    142         assert(static_cast<bool>(opt1) == false);
    143         assert(static_cast<bool>(opt2) == true);
    144         assert(*opt2 == 2);
    145         swap(opt1, opt2);
    146         assert(static_cast<bool>(opt1) == true);
    147         assert(*opt1 == 2);
    148         assert(static_cast<bool>(opt2) == false);
    149     }
    150     {
    151         optional<int> opt1(1);
    152         optional<int> opt2(2);
    153         static_assert(noexcept(swap(opt1, opt2)) == true, "");
    154         assert(static_cast<bool>(opt1) == true);
    155         assert(*opt1 == 1);
    156         assert(static_cast<bool>(opt2) == true);
    157         assert(*opt2 == 2);
    158         swap(opt1, opt2);
    159         assert(static_cast<bool>(opt1) == true);
    160         assert(*opt1 == 2);
    161         assert(static_cast<bool>(opt2) == true);
    162         assert(*opt2 == 1);
    163     }
    164     {
    165         optional<X> opt1;
    166         optional<X> opt2;
    167         static_assert(noexcept(swap(opt1, opt2)) == true, "");
    168         assert(static_cast<bool>(opt1) == false);
    169         assert(static_cast<bool>(opt2) == false);
    170         swap(opt1, opt2);
    171         assert(static_cast<bool>(opt1) == false);
    172         assert(static_cast<bool>(opt2) == false);
    173         assert(X::dtor_called == 0);
    174     }
    175     {
    176         optional<X> opt1(1);
    177         optional<X> opt2;
    178         static_assert(noexcept(swap(opt1, opt2)) == true, "");
    179         assert(static_cast<bool>(opt1) == true);
    180         assert(*opt1 == 1);
    181         assert(static_cast<bool>(opt2) == false);
    182         X::dtor_called = 0;
    183         swap(opt1, opt2);
    184         assert(X::dtor_called == 1);
    185         assert(static_cast<bool>(opt1) == false);
    186         assert(static_cast<bool>(opt2) == true);
    187         assert(*opt2 == 1);
    188     }
    189     {
    190         optional<X> opt1;
    191         optional<X> opt2(2);
    192         static_assert(noexcept(swap(opt1, opt2)) == true, "");
    193         assert(static_cast<bool>(opt1) == false);
    194         assert(static_cast<bool>(opt2) == true);
    195         assert(*opt2 == 2);
    196         X::dtor_called = 0;
    197         swap(opt1, opt2);
    198         assert(X::dtor_called == 1);
    199         assert(static_cast<bool>(opt1) == true);
    200         assert(*opt1 == 2);
    201         assert(static_cast<bool>(opt2) == false);
    202     }
    203     {
    204         optional<X> opt1(1);
    205         optional<X> opt2(2);
    206         static_assert(noexcept(swap(opt1, opt2)) == true, "");
    207         assert(static_cast<bool>(opt1) == true);
    208         assert(*opt1 == 1);
    209         assert(static_cast<bool>(opt2) == true);
    210         assert(*opt2 == 2);
    211         X::dtor_called = 0;
    212         swap(opt1, opt2);
    213         assert(X::dtor_called == 1);  // from inside std::swap
    214         assert(static_cast<bool>(opt1) == true);
    215         assert(*opt1 == 2);
    216         assert(static_cast<bool>(opt2) == true);
    217         assert(*opt2 == 1);
    218     }
    219     {
    220         optional<Y> opt1;
    221         optional<Y> opt2;
    222         static_assert(noexcept(swap(opt1, opt2)) == false, "");
    223         assert(static_cast<bool>(opt1) == false);
    224         assert(static_cast<bool>(opt2) == false);
    225         swap(opt1, opt2);
    226         assert(static_cast<bool>(opt1) == false);
    227         assert(static_cast<bool>(opt2) == false);
    228         assert(Y::dtor_called == 0);
    229     }
    230     {
    231         optional<Y> opt1(1);
    232         optional<Y> opt2;
    233         static_assert(noexcept(swap(opt1, opt2)) == false, "");
    234         assert(static_cast<bool>(opt1) == true);
    235         assert(*opt1 == 1);
    236         assert(static_cast<bool>(opt2) == false);
    237         Y::dtor_called = 0;
    238         swap(opt1, opt2);
    239         assert(Y::dtor_called == 1);
    240         assert(static_cast<bool>(opt1) == false);
    241         assert(static_cast<bool>(opt2) == true);
    242         assert(*opt2 == 1);
    243     }
    244     {
    245         optional<Y> opt1;
    246         optional<Y> opt2(2);
    247         static_assert(noexcept(swap(opt1, opt2)) == false, "");
    248         assert(static_cast<bool>(opt1) == false);
    249         assert(static_cast<bool>(opt2) == true);
    250         assert(*opt2 == 2);
    251         Y::dtor_called = 0;
    252         swap(opt1, opt2);
    253         assert(Y::dtor_called == 1);
    254         assert(static_cast<bool>(opt1) == true);
    255         assert(*opt1 == 2);
    256         assert(static_cast<bool>(opt2) == false);
    257     }
    258     {
    259         optional<Y> opt1(1);
    260         optional<Y> opt2(2);
    261         static_assert(noexcept(swap(opt1, opt2)) == false, "");
    262         assert(static_cast<bool>(opt1) == true);
    263         assert(*opt1 == 1);
    264         assert(static_cast<bool>(opt2) == true);
    265         assert(*opt2 == 2);
    266         Y::dtor_called = 0;
    267         swap(opt1, opt2);
    268         assert(Y::dtor_called == 0);
    269         assert(static_cast<bool>(opt1) == true);
    270         assert(*opt1 == 2);
    271         assert(static_cast<bool>(opt2) == true);
    272         assert(*opt2 == 1);
    273     }
    274     {
    275         optional<Z> opt1;
    276         optional<Z> opt2;
    277         static_assert(noexcept(swap(opt1, opt2)) == false, "");
    278         assert(static_cast<bool>(opt1) == false);
    279         assert(static_cast<bool>(opt2) == false);
    280         swap(opt1, opt2);
    281         assert(static_cast<bool>(opt1) == false);
    282         assert(static_cast<bool>(opt2) == false);
    283     }
    284 #ifndef TEST_HAS_NO_EXCEPTIONS
    285     {
    286         optional<Z> opt1;
    287         opt1.emplace(1);
    288         optional<Z> opt2;
    289         static_assert(noexcept(swap(opt1, opt2)) == false, "");
    290         assert(static_cast<bool>(opt1) == true);
    291         assert(*opt1 == 1);
    292         assert(static_cast<bool>(opt2) == false);
    293         try
    294         {
    295             swap(opt1, opt2);
    296             assert(false);
    297         }
    298         catch (int i)
    299         {
    300             assert(i == 7);
    301         }
    302         assert(static_cast<bool>(opt1) == true);
    303         assert(*opt1 == 1);
    304         assert(static_cast<bool>(opt2) == false);
    305     }
    306     {
    307         optional<Z> opt1;
    308         optional<Z> opt2;
    309         opt2.emplace(2);
    310         static_assert(noexcept(swap(opt1, opt2)) == false, "");
    311         assert(static_cast<bool>(opt1) == false);
    312         assert(static_cast<bool>(opt2) == true);
    313         assert(*opt2 == 2);
    314         try
    315         {
    316             swap(opt1, opt2);
    317             assert(false);
    318         }
    319         catch (int i)
    320         {
    321             assert(i == 7);
    322         }
    323         assert(static_cast<bool>(opt1) == false);
    324         assert(static_cast<bool>(opt2) == true);
    325         assert(*opt2 == 2);
    326     }
    327     {
    328         optional<Z> opt1;
    329         opt1.emplace(1);
    330         optional<Z> opt2;
    331         opt2.emplace(2);
    332         static_assert(noexcept(swap(opt1, opt2)) == false, "");
    333         assert(static_cast<bool>(opt1) == true);
    334         assert(*opt1 == 1);
    335         assert(static_cast<bool>(opt2) == true);
    336         assert(*opt2 == 2);
    337         try
    338         {
    339             swap(opt1, opt2);
    340             assert(false);
    341         }
    342         catch (int i)
    343         {
    344             assert(i == 6);
    345         }
    346         assert(static_cast<bool>(opt1) == true);
    347         assert(*opt1 == 1);
    348         assert(static_cast<bool>(opt2) == true);
    349         assert(*opt2 == 2);
    350     }
    351 #endif // TEST_HAS_NO_EXCEPTIONS
    352 }
    353