Home | History | Annotate | Download | only in optional.object.assign
      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 // optional<T>& operator=(optional<T>&& rhs)
     14 //     noexcept(is_nothrow_move_assignable<T>::value &&
     15 //              is_nothrow_move_constructible<T>::value);
     16 
     17 #include <optional>
     18 #include <type_traits>
     19 #include <cassert>
     20 
     21 #include "test_macros.h"
     22 #include "archetypes.hpp"
     23 
     24 using std::optional;
     25 
     26 struct X
     27 {
     28     static bool throw_now;
     29     static int alive;
     30 
     31     X() { ++alive; }
     32     X(X&&)
     33     {
     34         if (throw_now)
     35             TEST_THROW(6);
     36         ++alive;
     37     }
     38 
     39     X& operator=(X&&)
     40     {
     41         if (throw_now)
     42             TEST_THROW(42);
     43         return *this;
     44     }
     45 
     46     ~X() { assert(alive > 0); --alive; }
     47 };
     48 
     49 struct Y {};
     50 
     51 bool X::throw_now = false;
     52 int X::alive = 0;
     53 
     54 int main()
     55 {
     56     {
     57         static_assert(std::is_nothrow_move_assignable<optional<int>>::value, "");
     58         optional<int> opt;
     59         constexpr optional<int> opt2;
     60         opt = std::move(opt2);
     61         static_assert(static_cast<bool>(opt2) == false, "");
     62         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
     63     }
     64     {
     65         optional<int> opt;
     66         constexpr optional<int> opt2(2);
     67         opt = std::move(opt2);
     68         static_assert(static_cast<bool>(opt2) == true, "");
     69         static_assert(*opt2 == 2, "");
     70         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
     71         assert(*opt == *opt2);
     72     }
     73     {
     74         optional<int> opt(3);
     75         constexpr optional<int> opt2;
     76         opt = std::move(opt2);
     77         static_assert(static_cast<bool>(opt2) == false, "");
     78         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
     79     }
     80     {
     81         using T = TestTypes::TestType;
     82         T::reset();
     83         optional<T> opt(3);
     84         optional<T> opt2;
     85         assert(T::alive == 1);
     86         opt = std::move(opt2);
     87         assert(T::alive == 0);
     88         assert(static_cast<bool>(opt2) == false);
     89         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
     90     }
     91     {
     92         optional<int> opt(3);
     93         constexpr optional<int> opt2(2);
     94         opt = std::move(opt2);
     95         static_assert(static_cast<bool>(opt2) == true, "");
     96         static_assert(*opt2 == 2, "");
     97         assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
     98         assert(*opt == *opt2);
     99     }
    100 #ifndef TEST_HAS_NO_EXCEPTIONS
    101     {
    102         static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
    103         X::alive = 0;
    104         X::throw_now = false;
    105         optional<X> opt;
    106         optional<X> opt2(X{});
    107         assert(X::alive == 1);
    108         assert(static_cast<bool>(opt2) == true);
    109         try
    110         {
    111             X::throw_now = true;
    112             opt = std::move(opt2);
    113             assert(false);
    114         }
    115         catch (int i)
    116         {
    117             assert(i == 6);
    118             assert(static_cast<bool>(opt) == false);
    119         }
    120         assert(X::alive == 1);
    121     }
    122     assert(X::alive == 0);
    123     {
    124         static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
    125         X::throw_now = false;
    126         optional<X> opt(X{});
    127         optional<X> opt2(X{});
    128         assert(X::alive == 2);
    129         assert(static_cast<bool>(opt2) == true);
    130         try
    131         {
    132             X::throw_now = true;
    133             opt = std::move(opt2);
    134             assert(false);
    135         }
    136         catch (int i)
    137         {
    138             assert(i == 42);
    139             assert(static_cast<bool>(opt) == true);
    140         }
    141         assert(X::alive == 2);
    142     }
    143     assert(X::alive == 0);
    144 #endif // TEST_HAS_NO_EXCEPTIONS
    145     {
    146         static_assert(std::is_nothrow_move_assignable<optional<Y>>::value, "");
    147     }
    148     {
    149         struct ThrowsMove {
    150           ThrowsMove() noexcept {}
    151           ThrowsMove(ThrowsMove const&) noexcept {}
    152           ThrowsMove(ThrowsMove &&) noexcept(false) {}
    153           ThrowsMove& operator=(ThrowsMove const&) noexcept { return *this; }
    154           ThrowsMove& operator=(ThrowsMove &&) noexcept { return *this; }
    155         };
    156         static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMove>>::value, "");
    157         struct ThrowsMoveAssign {
    158           ThrowsMoveAssign() noexcept {}
    159           ThrowsMoveAssign(ThrowsMoveAssign const&) noexcept {}
    160           ThrowsMoveAssign(ThrowsMoveAssign &&) noexcept {}
    161           ThrowsMoveAssign& operator=(ThrowsMoveAssign const&) noexcept { return *this; }
    162           ThrowsMoveAssign& operator=(ThrowsMoveAssign &&) noexcept(false) { return *this; }
    163         };
    164         static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMoveAssign>>::value, "");
    165         struct NoThrowMove {
    166           NoThrowMove() noexcept(false) {}
    167           NoThrowMove(NoThrowMove const&) noexcept(false) {}
    168           NoThrowMove(NoThrowMove &&) noexcept {}
    169           NoThrowMove& operator=(NoThrowMove const&) noexcept { return *this; }
    170           NoThrowMove& operator=(NoThrowMove&&) noexcept { return *this; }
    171         };
    172         static_assert(std::is_nothrow_move_assignable<optional<NoThrowMove>>::value, "");
    173     }
    174 }
    175