//===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++98, c++03, c++11, c++14 // // optional(optional&& rhs); #include #include #include #include "test_macros.h" #include "archetypes.hpp" using std::optional; template void test(InitArgs&&... args) { const optional orig(std::forward(args)...); optional rhs(orig); bool rhs_engaged = static_cast(rhs); optional lhs = std::move(rhs); assert(static_cast(lhs) == rhs_engaged); if (rhs_engaged) assert(*lhs == *orig); } void test_throwing_ctor() { #ifndef TEST_HAS_NO_EXCEPTIONS struct Z { Z() : count(0) {} Z(Z&& o) : count(o.count + 1) { if (count == 2) throw 6; } int count; }; Z z; optional rhs(std::move(z)); try { optional lhs(std::move(rhs)); assert(false); } catch (int i) { assert(i == 6); } #endif } template void test_ref(InitArgs&&... args) { optional rhs(std::forward(args)...); bool rhs_engaged = static_cast(rhs); optional lhs = std::move(rhs); assert(static_cast(lhs) == rhs_engaged); if (rhs_engaged) assert(&(*lhs) == &(*rhs)); } void test_reference_extension() { #if defined(_LIBCPP_VERSION) && 0 // FIXME these extensions are currently disabled. using T = TestTypes::TestType; T::reset(); { T t; T::reset_constructors(); test_ref(); test_ref(t); assert(T::alive == 1); assert(T::constructed == 0); assert(T::assigned == 0); assert(T::destroyed == 0); } assert(T::destroyed == 1); assert(T::alive == 0); { T t; const T& ct = t; T::reset_constructors(); test_ref(); test_ref(t); test_ref(ct); assert(T::alive == 1); assert(T::constructed == 0); assert(T::assigned == 0); assert(T::destroyed == 0); } assert(T::alive == 0); assert(T::destroyed == 1); { T t; T::reset_constructors(); test_ref(); test_ref(std::move(t)); assert(T::alive == 1); assert(T::constructed == 0); assert(T::assigned == 0); assert(T::destroyed == 0); } assert(T::alive == 0); assert(T::destroyed == 1); { T t; const T& ct = t; T::reset_constructors(); test_ref(); test_ref(std::move(t)); test_ref(std::move(ct)); assert(T::alive == 1); assert(T::constructed == 0); assert(T::assigned == 0); assert(T::destroyed == 0); } assert(T::alive == 0); assert(T::destroyed == 1); { static_assert(!std::is_copy_constructible>::value, ""); static_assert(!std::is_copy_constructible>::value, ""); } #endif } int main() { test(); test(3); { using T = TestTypes::TestType; T::reset(); optional rhs; assert(T::alive == 0); const optional lhs(std::move(rhs)); assert(lhs.has_value() == false); assert(rhs.has_value() == false); assert(T::alive == 0); } TestTypes::TestType::reset(); { using T = TestTypes::TestType; T::reset(); optional rhs(42); assert(T::alive == 1); assert(T::value_constructed == 1); assert(T::move_constructed == 0); const optional lhs(std::move(rhs)); assert(lhs.has_value()); assert(rhs.has_value()); assert(lhs.value().value == 42); assert(rhs.value().value == -1); assert(T::move_constructed == 1); assert(T::alive == 2); } TestTypes::TestType::reset(); { using namespace ConstexprTestTypes; test(); test(42); } { using namespace TrivialTestTypes; test(); test(42); } { test_throwing_ctor(); } { struct ThrowsMove { ThrowsMove() noexcept(false) {} ThrowsMove(ThrowsMove const&) noexcept(false) {} ThrowsMove(ThrowsMove &&) noexcept(false) {} }; static_assert(!std::is_nothrow_move_constructible>::value, ""); struct NoThrowMove { NoThrowMove() noexcept(false) {} NoThrowMove(NoThrowMove const&) noexcept(false) {} NoThrowMove(NoThrowMove &&) noexcept(true) {} }; static_assert(std::is_nothrow_move_constructible>::value, ""); } { test_reference_extension(); } }