Home | History | Annotate | Download | only in optional.object.ctor
      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(optional<T>&& rhs);
     14 
     15 #include <optional>
     16 #include <type_traits>
     17 #include <cassert>
     18 
     19 #include "test_macros.h"
     20 #include "archetypes.hpp"
     21 
     22 using std::optional;
     23 
     24 template <class T, class ...InitArgs>
     25 void test(InitArgs&&... args)
     26 {
     27     const optional<T> orig(std::forward<InitArgs>(args)...);
     28     optional<T> rhs(orig);
     29     bool rhs_engaged = static_cast<bool>(rhs);
     30     optional<T> lhs = std::move(rhs);
     31     assert(static_cast<bool>(lhs) == rhs_engaged);
     32     if (rhs_engaged)
     33         assert(*lhs == *orig);
     34 }
     35 
     36 void test_throwing_ctor() {
     37 #ifndef TEST_HAS_NO_EXCEPTIONS
     38     struct Z {
     39       Z() : count(0) {}
     40       Z(Z&& o) : count(o.count + 1)
     41       { if (count == 2) throw 6; }
     42       int count;
     43     };
     44     Z z;
     45     optional<Z> rhs(std::move(z));
     46     try
     47     {
     48         optional<Z> lhs(std::move(rhs));
     49         assert(false);
     50     }
     51     catch (int i)
     52     {
     53         assert(i == 6);
     54     }
     55 #endif
     56 }
     57 
     58 
     59 template <class T, class ...InitArgs>
     60 void test_ref(InitArgs&&... args)
     61 {
     62     optional<T> rhs(std::forward<InitArgs>(args)...);
     63     bool rhs_engaged = static_cast<bool>(rhs);
     64     optional<T> lhs = std::move(rhs);
     65     assert(static_cast<bool>(lhs) == rhs_engaged);
     66     if (rhs_engaged)
     67         assert(&(*lhs) == &(*rhs));
     68 }
     69 
     70 void test_reference_extension()
     71 {
     72 #if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled.
     73     using T = TestTypes::TestType;
     74     T::reset();
     75     {
     76         T t;
     77         T::reset_constructors();
     78         test_ref<T&>();
     79         test_ref<T&>(t);
     80         assert(T::alive == 1);
     81         assert(T::constructed == 0);
     82         assert(T::assigned == 0);
     83         assert(T::destroyed == 0);
     84     }
     85     assert(T::destroyed == 1);
     86     assert(T::alive == 0);
     87     {
     88         T t;
     89         const T& ct = t;
     90         T::reset_constructors();
     91         test_ref<T const&>();
     92         test_ref<T const&>(t);
     93         test_ref<T const&>(ct);
     94         assert(T::alive == 1);
     95         assert(T::constructed == 0);
     96         assert(T::assigned == 0);
     97         assert(T::destroyed == 0);
     98     }
     99     assert(T::alive == 0);
    100     assert(T::destroyed == 1);
    101     {
    102         T t;
    103         T::reset_constructors();
    104         test_ref<T&&>();
    105         test_ref<T&&>(std::move(t));
    106         assert(T::alive == 1);
    107         assert(T::constructed == 0);
    108         assert(T::assigned == 0);
    109         assert(T::destroyed == 0);
    110     }
    111     assert(T::alive == 0);
    112     assert(T::destroyed == 1);
    113     {
    114         T t;
    115         const T& ct = t;
    116         T::reset_constructors();
    117         test_ref<T const&&>();
    118         test_ref<T const&&>(std::move(t));
    119         test_ref<T const&&>(std::move(ct));
    120         assert(T::alive == 1);
    121         assert(T::constructed == 0);
    122         assert(T::assigned == 0);
    123         assert(T::destroyed == 0);
    124     }
    125     assert(T::alive == 0);
    126     assert(T::destroyed == 1);
    127     {
    128         static_assert(!std::is_copy_constructible<std::optional<T&&>>::value, "");
    129         static_assert(!std::is_copy_constructible<std::optional<T const&&>>::value, "");
    130     }
    131 #endif
    132 }
    133 
    134 
    135 int main()
    136 {
    137     test<int>();
    138     test<int>(3);
    139     {
    140         optional<const int> o(42);
    141         optional<const int> o2(std::move(o));
    142         assert(*o2 == 42);
    143     }
    144     {
    145         using T = TestTypes::TestType;
    146         T::reset();
    147         optional<T> rhs;
    148         assert(T::alive == 0);
    149         const optional<T> lhs(std::move(rhs));
    150         assert(lhs.has_value() == false);
    151         assert(rhs.has_value() == false);
    152         assert(T::alive == 0);
    153     }
    154     TestTypes::TestType::reset();
    155     {
    156         using T = TestTypes::TestType;
    157         T::reset();
    158         optional<T> rhs(42);
    159         assert(T::alive == 1);
    160         assert(T::value_constructed == 1);
    161         assert(T::move_constructed == 0);
    162         const optional<T> lhs(std::move(rhs));
    163         assert(lhs.has_value());
    164         assert(rhs.has_value());
    165         assert(lhs.value().value == 42);
    166         assert(rhs.value().value == -1);
    167         assert(T::move_constructed == 1);
    168         assert(T::alive == 2);
    169     }
    170     TestTypes::TestType::reset();
    171     {
    172         using namespace ConstexprTestTypes;
    173         test<TestType>();
    174         test<TestType>(42);
    175     }
    176     {
    177         using namespace TrivialTestTypes;
    178         test<TestType>();
    179         test<TestType>(42);
    180     }
    181     {
    182         test_throwing_ctor();
    183     }
    184     {
    185         struct ThrowsMove {
    186           ThrowsMove() noexcept(false) {}
    187           ThrowsMove(ThrowsMove const&) noexcept(false) {}
    188           ThrowsMove(ThrowsMove &&) noexcept(false) {}
    189         };
    190         static_assert(!std::is_nothrow_move_constructible<optional<ThrowsMove>>::value, "");
    191         struct NoThrowMove {
    192           NoThrowMove() noexcept(false) {}
    193           NoThrowMove(NoThrowMove const&) noexcept(false) {}
    194           NoThrowMove(NoThrowMove &&) noexcept(true) {}
    195         };
    196         static_assert(std::is_nothrow_move_constructible<optional<NoThrowMove>>::value, "");
    197     }
    198     {
    199         test_reference_extension();
    200     }
    201 }
    202