diff options
Diffstat (limited to 'libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp')
-rw-r--r-- | libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp new file mode 100644 index 00000000000..6abdd0db63c --- /dev/null +++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp @@ -0,0 +1,261 @@ +//===----------------------------------------------------------------------===// +// +// 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> + +// template <class U> optional<T>& operator=(U&& v); + +#include <optional> +#include <type_traits> +#include <cassert> +#include <memory> + +#include "test_macros.h" +#include "archetypes.hpp" + +using std::optional; + +struct ThrowAssign { + static int dtor_called; + ThrowAssign() = default; + ThrowAssign(int) { TEST_THROW(42); } + ThrowAssign& operator=(int) { + TEST_THROW(42); + } + ~ThrowAssign() { ++dtor_called; } +}; +int ThrowAssign::dtor_called = 0; + +template <class T, class Arg = T, bool Expect = true> +void assert_assignable() { + static_assert(std::is_assignable<optional<T>&, Arg>::value == Expect, ""); + static_assert(!std::is_assignable<const optional<T>&, Arg>::value, ""); +} + +struct MismatchType { + explicit MismatchType(int) {} + explicit MismatchType(char*) {} + explicit MismatchType(int*) = delete; + MismatchType& operator=(int) { return *this; } + MismatchType& operator=(int*) { return *this; } + MismatchType& operator=(char*) = delete; +}; + +void test_sfinae() { + using I = TestTypes::TestType; + using E = ExplicitTestTypes::TestType; + assert_assignable<int>(); + assert_assignable<int, int&>(); + assert_assignable<int, int const&>(); + // Implicit test type + assert_assignable<I, I const&>(); + assert_assignable<I, I&&>(); + assert_assignable<I, int>(); + assert_assignable<I, void*, false>(); + // Explicit test type + assert_assignable<E, E const&>(); + assert_assignable<E, E &&>(); + assert_assignable<E, int>(); + assert_assignable<E, void*, false>(); + // Mismatch type + assert_assignable<MismatchType, int>(); + assert_assignable<MismatchType, int*, false>(); + assert_assignable<MismatchType, char*, false>(); +} + +void test_with_test_type() +{ + using T = TestTypes::TestType; + T::reset(); + { // to empty + optional<T> opt; + opt = 3; + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 0); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // to existing + optional<T> opt(42); + T::reset_constructors(); + opt = 3; + assert(T::alive == 1); + assert(T::constructed == 0); + assert(T::assigned == 1); + assert(T::value_assigned == 1); + assert(T::destroyed == 0); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // test default argument + optional<T> opt; + T::reset_constructors(); + opt = {1, 2}; + assert(T::alive == 1); + assert(T::constructed == 2); + assert(T::value_constructed == 1); + assert(T::move_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1, 2)); + } + { // test default argument + optional<T> opt(42); + T::reset_constructors(); + opt = {1, 2}; + assert(T::alive == 1); + assert(T::constructed == 1); + assert(T::value_constructed == 1); + assert(T::assigned == 1); + assert(T::move_assigned == 1); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1, 2)); + } + { // test default argument + optional<T> opt; + T::reset_constructors(); + opt = {1}; + assert(T::alive == 1); + assert(T::constructed == 2); + assert(T::value_constructed == 1); + assert(T::move_constructed == 1); + assert(T::assigned == 0); + assert(T::destroyed == 1); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1)); + } + { // test default argument + optional<T> opt(42); + T::reset_constructors(); + opt = {}; + assert(static_cast<bool>(opt) == false); + assert(T::alive == 0); + assert(T::constructed == 0); + assert(T::assigned == 0); + assert(T::destroyed == 1); + } +} + +template <class T, class Value = int> +void test_with_type() { + { // to empty + optional<T> opt; + opt = Value(3); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // to existing + optional<T> opt(Value(42)); + opt = Value(3); + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // test const + optional<T> opt(Value(42)); + const T t(Value(3)); + opt = t; + assert(static_cast<bool>(opt) == true); + assert(*opt == T(3)); + } + { // test default argument + optional<T> opt; + opt = {Value(1)}; + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1)); + } + { // test default argument + optional<T> opt(Value(42)); + opt = {}; + assert(static_cast<bool>(opt) == false); + } +} + +template <class T> +void test_with_type_multi() { + test_with_type<T>(); + { // test default argument + optional<T> opt; + opt = {1, 2}; + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1, 2)); + } + { // test default argument + optional<T> opt(42); + opt = {1, 2}; + assert(static_cast<bool>(opt) == true); + assert(*opt == T(1, 2)); + } +} + +void test_throws() +{ +#ifndef TEST_HAS_NO_EXCEPTIONS + using T = ThrowAssign; + { + using T = ThrowAssign; + optional<T> opt; + try { + opt = 42; + assert(false); + } catch (int) {} + assert(static_cast<bool>(opt) == false); + } + assert(T::dtor_called == 0); + { + T::dtor_called = 0; + optional<T> opt(std::in_place); + try { + opt = 42; + assert(false); + } catch (int) {} + assert(static_cast<bool>(opt) == true); + assert(T::dtor_called == 0); + } + assert(T::dtor_called == 1); +#endif +} + +enum MyEnum { Zero, One, Two, Three, FortyTwo = 42 }; + +using Fn = void(*)(); + +int main() +{ + test_sfinae(); + // Test with instrumented type + test_with_test_type(); + // Test with various scalar types + test_with_type<int>(); + test_with_type<MyEnum, MyEnum>(); + test_with_type<int, MyEnum>(); + test_with_type<Fn, Fn>(); + // Test types with multi argument constructors + test_with_type_multi<ConstexprTestTypes::TestType>(); + test_with_type_multi<TrivialTestTypes::TestType>(); + // Test move only types + { + optional<std::unique_ptr<int>> opt; + opt = std::unique_ptr<int>(new int(3)); + assert(static_cast<bool>(opt) == true); + assert(**opt == 3); + } + { + optional<std::unique_ptr<int>> opt(std::unique_ptr<int>(new int(2))); + opt = std::unique_ptr<int>(new int(3)); + assert(static_cast<bool>(opt) == true); + assert(**opt == 3); + } + test_throws(); +} |