summaryrefslogtreecommitdiffstats
path: root/libcxx/test/std/utilities/optional/optional.object/optional.object.assign
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx/test/std/utilities/optional/optional.object/optional.object.assign')
-rw-r--r--libcxx/test/std/utilities/optional/optional.object/optional.object.assign/assign_value.pass.cpp261
-rw-r--r--libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp254
-rw-r--r--libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp102
-rw-r--r--libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp237
-rw-r--r--libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp113
-rw-r--r--libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp174
-rw-r--r--libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp67
-rw-r--r--libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp268
8 files changed, 1476 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();
+}
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp
new file mode 100644
index 00000000000..d471c053c90
--- /dev/null
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/const_optional_U.pass.cpp
@@ -0,0 +1,254 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+// From LWG2451:
+// template<class U>
+// optional<T>& operator=(const optional<U>& rhs);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+
+struct X
+{
+ static bool throw_now;
+
+ X() = default;
+ X(int)
+ {
+ if (throw_now)
+ TEST_THROW(6);
+ }
+};
+
+bool X::throw_now = false;
+
+struct Y1
+{
+ Y1() = default;
+ Y1(const int&) {}
+ Y1& operator=(const Y1&) = delete;
+};
+
+struct Y2
+{
+ Y2() = default;
+ Y2(const int&) = delete;
+ Y2& operator=(const int&) { return *this; }
+};
+
+template <class T>
+struct AssignableFrom {
+ static int type_constructed;
+ static int type_assigned;
+static int int_constructed;
+ static int int_assigned;
+
+ static void reset() {
+ type_constructed = int_constructed = 0;
+ type_assigned = int_assigned = 0;
+ }
+
+ AssignableFrom() = default;
+
+ explicit AssignableFrom(T) { ++type_constructed; }
+ AssignableFrom& operator=(T) { ++type_assigned; return *this; }
+
+ AssignableFrom(int) { ++int_constructed; }
+ AssignableFrom& operator=(int) { ++int_assigned; return *this; }
+private:
+ AssignableFrom(AssignableFrom const&) = delete;
+ AssignableFrom& operator=(AssignableFrom const&) = delete;
+};
+
+template <class T> int AssignableFrom<T>::type_constructed = 0;
+template <class T> int AssignableFrom<T>::type_assigned = 0;
+template <class T> int AssignableFrom<T>::int_constructed = 0;
+template <class T> int AssignableFrom<T>::int_assigned = 0;
+
+
+void test_with_test_type() {
+ using T = TestTypes::TestType;
+ T::reset();
+ { // non-empty to empty
+ T::reset_constructors();
+ optional<T> opt;
+ const optional<int> other(42);
+ opt = other;
+ 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>(other) == true);
+ assert(*other == 42);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(42));
+ }
+ assert(T::alive == 0);
+ { // non-empty to non-empty
+ optional<T> opt(101);
+ const optional<int> other(42);
+ T::reset_constructors();
+ opt = other;
+ 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>(other) == true);
+ assert(*other == 42);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(42));
+ }
+ assert(T::alive == 0);
+ { // empty to non-empty
+ optional<T> opt(101);
+ const optional<int> other;
+ T::reset_constructors();
+ opt = other;
+ assert(T::alive == 0);
+ assert(T::constructed == 0);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(other) == false);
+ assert(static_cast<bool>(opt) == false);
+ }
+ assert(T::alive == 0);
+ { // empty to empty
+ optional<T> opt;
+ const optional<int> other;
+ T::reset_constructors();
+ opt = other;
+ assert(T::alive == 0);
+ assert(T::constructed == 0);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 0);
+ assert(static_cast<bool>(other) == false);
+ assert(static_cast<bool>(opt) == false);
+ }
+ assert(T::alive == 0);
+}
+
+void test_ambigious_assign() {
+ using OptInt = std::optional<int>;
+ {
+ using T = AssignableFrom<OptInt const&>;
+ const OptInt a(42);
+ T::reset();
+ {
+ std::optional<T> t;
+ t = a;
+ assert(T::type_constructed == 1);
+ assert(T::type_assigned == 0);
+ assert(T::int_constructed == 0);
+ assert(T::int_assigned == 0);
+ }
+ T::reset();
+ {
+ std::optional<T> t(42);
+ t = a;
+ assert(T::type_constructed == 0);
+ assert(T::type_assigned == 1);
+ assert(T::int_constructed == 1);
+ assert(T::int_assigned == 0);
+ }
+ T::reset();
+ {
+ std::optional<T> t(42);
+ t = std::move(a);
+ assert(T::type_constructed == 0);
+ assert(T::type_assigned == 1);
+ assert(T::int_constructed == 1);
+ assert(T::int_assigned == 0);
+ }
+ }
+ {
+ using T = AssignableFrom<OptInt&>;
+ OptInt a(42);
+ T::reset();
+ {
+ std::optional<T> t;
+ t = a;
+ assert(T::type_constructed == 1);
+ assert(T::type_assigned == 0);
+ assert(T::int_constructed == 0);
+ assert(T::int_assigned == 0);
+ }
+ {
+ using Opt = std::optional<T>;
+ static_assert(!std::is_assignable_v<Opt&, OptInt const&>, "");
+ }
+ }
+}
+
+
+int main()
+{
+ test_with_test_type();
+ test_ambigious_assign();
+ {
+ optional<int> opt;
+ constexpr optional<short> opt2;
+ opt = opt2;
+ static_assert(static_cast<bool>(opt2) == false, "");
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ }
+ {
+ optional<int> opt;
+ constexpr optional<short> opt2(short{2});
+ opt = opt2;
+ static_assert(static_cast<bool>(opt2) == true, "");
+ static_assert(*opt2 == 2, "");
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ assert(*opt == *opt2);
+ }
+ {
+ optional<int> opt(3);
+ constexpr optional<short> opt2;
+ opt = opt2;
+ static_assert(static_cast<bool>(opt2) == false, "");
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ }
+ {
+ optional<int> opt(3);
+ constexpr optional<short> opt2(short{2});
+ opt = opt2;
+ static_assert(static_cast<bool>(opt2) == true, "");
+ static_assert(*opt2 == 2, "");
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ assert(*opt == *opt2);
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ optional<X> opt;
+ optional<int> opt2(42);
+ assert(static_cast<bool>(opt2) == true);
+ try
+ {
+ X::throw_now = true;
+ opt = opt2;
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ assert(static_cast<bool>(opt) == false);
+ }
+ }
+#endif
+}
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
new file mode 100644
index 00000000000..98c90aa1d4f
--- /dev/null
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/copy.pass.cpp
@@ -0,0 +1,102 @@
+//===----------------------------------------------------------------------===//
+//
+// 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<T>& operator=(const optional<T>& rhs);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+
+struct X
+{
+ static bool throw_now;
+
+ X() = default;
+ X(const X&)
+ {
+ if (throw_now)
+ TEST_THROW(6);
+ }
+};
+
+bool X::throw_now = false;
+
+template <class Tp>
+constexpr bool assign_empty(optional<Tp>&& lhs) {
+ const optional<Tp> rhs;
+ lhs = rhs;
+ return !lhs.has_value() && !rhs.has_value();
+}
+
+template <class Tp>
+constexpr bool assign_value(optional<Tp>&& lhs) {
+ const optional<Tp> rhs(101);
+ lhs = rhs;
+ return lhs.has_value() && rhs.has_value() && *lhs == *rhs;
+}
+
+int main()
+{
+ {
+ using O = optional<int>;
+ LIBCPP_STATIC_ASSERT(assign_empty(O{42}), "");
+ LIBCPP_STATIC_ASSERT(assign_value(O{42}), "");
+ assert(assign_empty(O{42}));
+ assert(assign_value(O{42}));
+ }
+ {
+ using O = optional<TrivialTestTypes::TestType>;
+ LIBCPP_STATIC_ASSERT(assign_empty(O{42}), "");
+ LIBCPP_STATIC_ASSERT(assign_value(O{42}), "");
+ assert(assign_empty(O{42}));
+ assert(assign_value(O{42}));
+ }
+ {
+ using O = optional<TestTypes::TestType>;
+ assert(assign_empty(O{42}));
+ assert(assign_value(O{42}));
+ }
+ {
+ using T = TestTypes::TestType;
+ T::reset();
+ optional<T> opt(3);
+ const optional<T> opt2;
+ assert(T::alive == 1);
+ opt = opt2;
+ assert(T::alive == 0);
+ assert(!opt2.has_value());
+ assert(!opt.has_value());
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ optional<X> opt;
+ optional<X> opt2(X{});
+ assert(static_cast<bool>(opt2) == true);
+ try
+ {
+ X::throw_now = true;
+ opt = opt2;
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ assert(static_cast<bool>(opt) == false);
+ }
+ }
+#endif
+}
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp
new file mode 100644
index 00000000000..be17aa6fc51
--- /dev/null
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace.pass.cpp
@@ -0,0 +1,237 @@
+//===----------------------------------------------------------------------===//
+//
+// 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... Args> void optional<T>::emplace(Args&&... args);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+#include <memory>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+
+class X
+{
+ int i_;
+ int j_ = 0;
+public:
+ X() : i_(0) {}
+ X(int i) : i_(i) {}
+ X(int i, int j) : i_(i), j_(j) {}
+
+ friend bool operator==(const X& x, const X& y)
+ {return x.i_ == y.i_ && x.j_ == y.j_;}
+};
+
+class Y
+{
+public:
+ static bool dtor_called;
+ Y() = default;
+ Y(int) { TEST_THROW(6);}
+ ~Y() {dtor_called = true;}
+};
+
+bool Y::dtor_called = false;
+
+template <class T>
+void test_one_arg() {
+ using Opt = std::optional<T>;
+ {
+ Opt opt;
+ opt.emplace();
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(0));
+ }
+ {
+ Opt opt;
+ opt.emplace(1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(1));
+ }
+ {
+ Opt opt(2);
+ opt.emplace();
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(0));
+ }
+ {
+ Opt opt(2);
+ opt.emplace(1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(1));
+ }
+}
+
+
+template <class T>
+void test_multi_arg()
+{
+ test_one_arg<T>();
+ using Opt = std::optional<T>;
+ Opt opt;
+ {
+ opt.emplace(101, 41);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(101, 41));
+ }
+ {
+ Opt opt;
+ opt.emplace({1, 2, 3, 4});
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(4)); // T sets its value to the size of the init list
+ }
+ {
+ Opt opt;
+ opt.emplace({1, 2, 3, 4, 5}, 6);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(5)); // T sets its value to the size of the init list
+ }
+}
+
+template <class T>
+void test_on_test_type() {
+
+ T::reset();
+ optional<T> opt;
+ assert(T::alive == 0);
+ {
+ T::reset_constructors();
+ opt.emplace();
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::default_constructed == 1);
+ assert(T::destroyed == 0);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T());
+ }
+ {
+ T::reset_constructors();
+ opt.emplace();
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::default_constructed == 1);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T());
+ }
+ {
+ T::reset_constructors();
+ opt.emplace(101);
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::value_constructed == 1);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(101));
+ }
+ {
+ T::reset_constructors();
+ opt.emplace(-10, 99);
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::value_constructed == 1);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(-10, 99));
+ }
+ {
+ T::reset_constructors();
+ opt.emplace(-10, 99);
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::value_constructed == 1);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(-10, 99));
+ }
+ {
+ T::reset_constructors();
+ opt.emplace({-10, 99, 42, 1});
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::value_constructed == 1);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(4)); // size of the initializer list
+ }
+ {
+ T::reset_constructors();
+ opt.emplace({-10, 99, 42, 1}, 42);
+ assert(T::alive == 1);
+ assert(T::constructed == 1);
+ assert(T::value_constructed == 1);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(4)); // size of the initializer list
+ }
+}
+
+
+
+int main()
+{
+ {
+ test_on_test_type<TestTypes::TestType>();
+ test_on_test_type<ExplicitTestTypes::TestType>();
+ }
+ {
+ using T = int;
+ test_one_arg<T>();
+ test_one_arg<const T>();
+ }
+ {
+ using T = ConstexprTestTypes::TestType;
+ test_multi_arg<T>();
+ }
+ {
+ using T = ExplicitConstexprTestTypes::TestType;
+ test_multi_arg<T>();
+ }
+ {
+ using T = TrivialTestTypes::TestType;
+ test_multi_arg<T>();
+ }
+ {
+ using T = ExplicitTrivialTestTypes::TestType;
+ test_multi_arg<T>();
+ }
+ {
+ optional<const int> opt;
+ opt.emplace(42);
+ assert(*opt == 42);
+ opt.emplace();
+ assert(*opt == 0);
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ Y::dtor_called = false;
+ {
+ Y y;
+ optional<Y> opt(y);
+ try
+ {
+ assert(static_cast<bool>(opt) == true);
+ assert(Y::dtor_called == false);
+ opt.emplace(1);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ assert(static_cast<bool>(opt) == false);
+ assert(Y::dtor_called == true);
+ }
+ }
+#endif
+}
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp
new file mode 100644
index 00000000000..1c3c69a7030
--- /dev/null
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/emplace_initializer_list.pass.cpp
@@ -0,0 +1,113 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, class... Args>
+// void optional<T>::emplace(initializer_list<U> il, Args&&... args);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+#include <vector>
+
+#include "test_macros.h"
+
+using std::optional;
+
+class X
+{
+ int i_;
+ int j_ = 0;
+public:
+ static bool dtor_called;
+ constexpr X() : i_(0) {}
+ constexpr X(int i) : i_(i) {}
+ constexpr X(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {}
+ ~X() {dtor_called = true;}
+
+ friend constexpr bool operator==(const X& x, const X& y)
+ {return x.i_ == y.i_ && x.j_ == y.j_;}
+};
+
+bool X::dtor_called = false;
+
+class Y
+{
+ int i_;
+ int j_ = 0;
+public:
+ constexpr Y() : i_(0) {}
+ constexpr Y(int i) : i_(i) {}
+ constexpr Y(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1]) {}
+
+ friend constexpr bool operator==(const Y& x, const Y& y)
+ {return x.i_ == y.i_ && x.j_ == y.j_;}
+};
+
+class Z
+{
+ int i_;
+ int j_ = 0;
+public:
+ static bool dtor_called;
+ Z() : i_(0) {}
+ Z(int i) : i_(i) {}
+ Z(std::initializer_list<int> il) : i_(il.begin()[0]), j_(il.begin()[1])
+ { TEST_THROW(6);}
+ ~Z() {dtor_called = true;}
+
+ friend bool operator==(const Z& x, const Z& y)
+ {return x.i_ == y.i_ && x.j_ == y.j_;}
+};
+
+bool Z::dtor_called = false;
+
+int main()
+{
+ {
+ X x;
+ optional<X> opt(x);
+ assert(X::dtor_called == false);
+ opt.emplace({1, 2});
+ assert(X::dtor_called == true);
+ assert(*opt == X({1, 2}));
+ }
+ {
+ optional<std::vector<int>> opt;
+ opt.emplace({1, 2, 3}, std::allocator<int>());
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == std::vector<int>({1, 2, 3}));
+ }
+ {
+ optional<Y> opt;
+ opt.emplace({1, 2});
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == Y({1, 2}));
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ Z z;
+ optional<Z> opt(z);
+ try
+ {
+ assert(static_cast<bool>(opt) == true);
+ assert(Z::dtor_called == false);
+ opt.emplace({1, 2});
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ assert(static_cast<bool>(opt) == false);
+ assert(Z::dtor_called == true);
+ }
+ }
+#endif
+}
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp
new file mode 100644
index 00000000000..3ba261b5246
--- /dev/null
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/move.pass.cpp
@@ -0,0 +1,174 @@
+//===----------------------------------------------------------------------===//
+//
+// 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<T>& operator=(optional<T>&& rhs)
+// noexcept(is_nothrow_move_assignable<T>::value &&
+// is_nothrow_move_constructible<T>::value);
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+
+struct X
+{
+ static bool throw_now;
+ static int alive;
+
+ X() { ++alive; }
+ X(X&&)
+ {
+ if (throw_now)
+ TEST_THROW(6);
+ ++alive;
+ }
+
+ X& operator=(X&&)
+ {
+ if (throw_now)
+ TEST_THROW(42);
+ return *this;
+ }
+
+ ~X() { assert(alive > 0); --alive; }
+};
+
+struct Y {};
+
+bool X::throw_now = false;
+int X::alive = 0;
+
+int main()
+{
+ {
+ static_assert(std::is_nothrow_move_assignable<optional<int>>::value, "");
+ optional<int> opt;
+ constexpr optional<int> opt2;
+ opt = std::move(opt2);
+ static_assert(static_cast<bool>(opt2) == false, "");
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ }
+ {
+ optional<int> opt;
+ constexpr optional<int> opt2(2);
+ opt = std::move(opt2);
+ static_assert(static_cast<bool>(opt2) == true, "");
+ static_assert(*opt2 == 2, "");
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ assert(*opt == *opt2);
+ }
+ {
+ optional<int> opt(3);
+ constexpr optional<int> opt2;
+ opt = std::move(opt2);
+ static_assert(static_cast<bool>(opt2) == false, "");
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ }
+ {
+ using T = TestTypes::TestType;
+ T::reset();
+ optional<T> opt(3);
+ optional<T> opt2;
+ assert(T::alive == 1);
+ opt = std::move(opt2);
+ assert(T::alive == 0);
+ assert(static_cast<bool>(opt2) == false);
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ }
+ {
+ optional<int> opt(3);
+ constexpr optional<int> opt2(2);
+ opt = std::move(opt2);
+ static_assert(static_cast<bool>(opt2) == true, "");
+ static_assert(*opt2 == 2, "");
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ assert(*opt == *opt2);
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
+ X::alive = 0;
+ X::throw_now = false;
+ optional<X> opt;
+ optional<X> opt2(X{});
+ assert(X::alive == 1);
+ assert(static_cast<bool>(opt2) == true);
+ try
+ {
+ X::throw_now = true;
+ opt = std::move(opt2);
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ assert(static_cast<bool>(opt) == false);
+ }
+ assert(X::alive == 1);
+ }
+ assert(X::alive == 0);
+ {
+ static_assert(!std::is_nothrow_move_assignable<optional<X>>::value, "");
+ X::throw_now = false;
+ optional<X> opt(X{});
+ optional<X> opt2(X{});
+ assert(X::alive == 2);
+ assert(static_cast<bool>(opt2) == true);
+ try
+ {
+ X::throw_now = true;
+ opt = std::move(opt2);
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 42);
+ assert(static_cast<bool>(opt) == true);
+ }
+ assert(X::alive == 2);
+ }
+ assert(X::alive == 0);
+#endif // TEST_HAS_NO_EXCEPTIONS
+ {
+ static_assert(std::is_nothrow_move_assignable<optional<Y>>::value, "");
+ }
+ {
+ struct ThrowsMove {
+ ThrowsMove() noexcept {}
+ ThrowsMove(ThrowsMove const&) noexcept {}
+ ThrowsMove(ThrowsMove &&) noexcept(false) {}
+ ThrowsMove& operator=(ThrowsMove const&) noexcept { return *this; }
+ ThrowsMove& operator=(ThrowsMove &&) noexcept { return *this; }
+ };
+ static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMove>>::value, "");
+ struct ThrowsMoveAssign {
+ ThrowsMoveAssign() noexcept {}
+ ThrowsMoveAssign(ThrowsMoveAssign const&) noexcept {}
+ ThrowsMoveAssign(ThrowsMoveAssign &&) noexcept {}
+ ThrowsMoveAssign& operator=(ThrowsMoveAssign const&) noexcept { return *this; }
+ ThrowsMoveAssign& operator=(ThrowsMoveAssign &&) noexcept(false) { return *this; }
+ };
+ static_assert(!std::is_nothrow_move_assignable<optional<ThrowsMoveAssign>>::value, "");
+ struct NoThrowMove {
+ NoThrowMove() noexcept(false) {}
+ NoThrowMove(NoThrowMove const&) noexcept(false) {}
+ NoThrowMove(NoThrowMove &&) noexcept {}
+ NoThrowMove& operator=(NoThrowMove const&) noexcept { return *this; }
+ NoThrowMove& operator=(NoThrowMove&&) noexcept { return *this; }
+ };
+ static_assert(std::is_nothrow_move_assignable<optional<NoThrowMove>>::value, "");
+ }
+}
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp
new file mode 100644
index 00000000000..991f4334304
--- /dev/null
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/nullopt_t.pass.cpp
@@ -0,0 +1,67 @@
+//===----------------------------------------------------------------------===//
+//
+// 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<T>& operator=(nullopt_t) noexcept;
+
+#include <optional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+using std::nullopt_t;
+using std::nullopt;
+
+int main()
+{
+ {
+ optional<int> opt;
+ static_assert(noexcept(opt = nullopt) == true, "");
+ opt = nullopt;
+ assert(static_cast<bool>(opt) == false);
+ }
+ {
+ optional<int> opt(3);
+ opt = nullopt;
+ assert(static_cast<bool>(opt) == false);
+ }
+ using TT = TestTypes::TestType;
+ TT::reset();
+ {
+ optional<TT> opt;
+ static_assert(noexcept(opt = nullopt) == true, "");
+ assert(TT::destroyed == 0);
+ opt = nullopt;
+ assert(TT::constructed == 0);
+ assert(TT::alive == 0);
+ assert(TT::destroyed == 0);
+ assert(static_cast<bool>(opt) == false);
+ }
+ assert(TT::alive == 0);
+ assert(TT::destroyed == 0);
+ TT::reset();
+ {
+ optional<TT> opt(42);
+ assert(TT::destroyed == 0);
+ TT::reset_constructors();
+ opt = nullopt;
+ assert(TT::constructed == 0);
+ assert(TT::alive == 0);
+ assert(TT::destroyed == 1);
+ assert(static_cast<bool>(opt) == false);
+ }
+ assert(TT::alive == 0);
+ assert(TT::destroyed == 1);
+ TT::reset();
+}
diff --git a/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp
new file mode 100644
index 00000000000..db7fc19bfb1
--- /dev/null
+++ b/libcxx/test/std/utilities/optional/optional.object/optional.object.assign/optional_U.pass.cpp
@@ -0,0 +1,268 @@
+//===----------------------------------------------------------------------===//
+//
+// 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>
+
+// From LWG2451:
+// template <class U>
+// optional<T>& operator=(optional<U>&& rhs);
+
+#include <optional>
+#include <type_traits>
+#include <memory>
+#include <cassert>
+
+#include "test_macros.h"
+#include "archetypes.hpp"
+
+using std::optional;
+
+struct X
+{
+ static bool throw_now;
+
+ X() = default;
+ X(int &&)
+ {
+ if (throw_now)
+ TEST_THROW(6);
+ }
+};
+
+bool X::throw_now = false;
+
+struct Y1
+{
+ Y1() = default;
+ Y1(const int&) {}
+ Y1& operator=(const Y1&) = delete;
+};
+
+struct Y2
+{
+ Y2() = default;
+ Y2(const int&) = delete;
+ Y2& operator=(const int&) { return *this; }
+};
+
+class B {};
+class D : public B {};
+
+
+template <class T>
+struct AssignableFrom {
+ static int type_constructed;
+ static int type_assigned;
+static int int_constructed;
+ static int int_assigned;
+
+ static void reset() {
+ type_constructed = int_constructed = 0;
+ type_assigned = int_assigned = 0;
+ }
+
+ AssignableFrom() = default;
+
+ explicit AssignableFrom(T) { ++type_constructed; }
+ AssignableFrom& operator=(T) { ++type_assigned; return *this; }
+
+ AssignableFrom(int) { ++int_constructed; }
+ AssignableFrom& operator=(int) { ++int_assigned; return *this; }
+private:
+ AssignableFrom(AssignableFrom const&) = delete;
+ AssignableFrom& operator=(AssignableFrom const&) = delete;
+};
+
+template <class T> int AssignableFrom<T>::type_constructed = 0;
+template <class T> int AssignableFrom<T>::type_assigned = 0;
+template <class T> int AssignableFrom<T>::int_constructed = 0;
+template <class T> int AssignableFrom<T>::int_assigned = 0;
+
+void test_with_test_type() {
+ using T = TestTypes::TestType;
+ T::reset();
+ { // non-empty to empty
+ T::reset_constructors();
+ optional<T> opt;
+ optional<int> other(42);
+ opt = std::move(other);
+ 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>(other) == true);
+ assert(*other == 42);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(42));
+ }
+ assert(T::alive == 0);
+ { // non-empty to non-empty
+ optional<T> opt(101);
+ optional<int> other(42);
+ T::reset_constructors();
+ opt = std::move(other);
+ 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>(other) == true);
+ assert(*other == 42);
+ assert(static_cast<bool>(opt) == true);
+ assert(*opt == T(42));
+ }
+ assert(T::alive == 0);
+ { // empty to non-empty
+ optional<T> opt(101);
+ optional<int> other;
+ T::reset_constructors();
+ opt = std::move(other);
+ assert(T::alive == 0);
+ assert(T::constructed == 0);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 1);
+ assert(static_cast<bool>(other) == false);
+ assert(static_cast<bool>(opt) == false);
+ }
+ assert(T::alive == 0);
+ { // empty to empty
+ optional<T> opt;
+ optional<int> other;
+ T::reset_constructors();
+ opt = std::move(other);
+ assert(T::alive == 0);
+ assert(T::constructed == 0);
+ assert(T::assigned == 0);
+ assert(T::destroyed == 0);
+ assert(static_cast<bool>(other) == false);
+ assert(static_cast<bool>(opt) == false);
+ }
+ assert(T::alive == 0);
+}
+
+
+void test_ambigious_assign() {
+ using OptInt = std::optional<int>;
+ {
+ using T = AssignableFrom<OptInt&&>;
+ T::reset();
+ {
+ OptInt a(42);
+ std::optional<T> t;
+ t = std::move(a);
+ assert(T::type_constructed == 1);
+ assert(T::type_assigned == 0);
+ assert(T::int_constructed == 0);
+ assert(T::int_assigned == 0);
+ }
+ {
+ using Opt = std::optional<T>;
+ static_assert(!std::is_assignable<Opt&, const OptInt&&>::value, "");
+ static_assert(!std::is_assignable<Opt&, const OptInt&>::value, "");
+ static_assert(!std::is_assignable<Opt&, OptInt&>::value, "");
+ }
+ }
+ {
+ using T = AssignableFrom<OptInt const&&>;
+ T::reset();
+ {
+ const OptInt a(42);
+ std::optional<T> t;
+ t = std::move(a);
+ assert(T::type_constructed == 1);
+ assert(T::type_assigned == 0);
+ assert(T::int_constructed == 0);
+ assert(T::int_assigned == 0);
+ }
+ T::reset();
+ {
+ OptInt a(42);
+ std::optional<T> t;
+ t = std::move(a);
+ assert(T::type_constructed == 1);
+ assert(T::type_assigned == 0);
+ assert(T::int_constructed == 0);
+ assert(T::int_assigned == 0);
+ }
+ {
+ using Opt = std::optional<T>;
+ static_assert(std::is_assignable<Opt&, OptInt&&>::value, "");
+ static_assert(!std::is_assignable<Opt&, const OptInt&>::value, "");
+ static_assert(!std::is_assignable<Opt&, OptInt&>::value, "");
+ }
+ }
+}
+
+
+int main()
+{
+ test_with_test_type();
+ test_ambigious_assign();
+ {
+ optional<int> opt;
+ optional<short> opt2;
+ opt = std::move(opt2);
+ assert(static_cast<bool>(opt2) == false);
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ }
+ {
+ optional<int> opt;
+ optional<short> opt2(short{2});
+ opt = std::move(opt2);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 2);
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ assert(*opt == *opt2);
+ }
+ {
+ optional<int> opt(3);
+ optional<short> opt2;
+ opt = std::move(opt2);
+ assert(static_cast<bool>(opt2) == false);
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ }
+ {
+ optional<int> opt(3);
+ optional<short> opt2(short{2});
+ opt = std::move(opt2);
+ assert(static_cast<bool>(opt2) == true);
+ assert(*opt2 == 2);
+ assert(static_cast<bool>(opt) == static_cast<bool>(opt2));
+ assert(*opt == *opt2);
+ }
+ {
+ optional<std::unique_ptr<B>> opt;
+ optional<std::unique_ptr<D>> other(new D());
+ opt = std::move(other);
+ assert(static_cast<bool>(opt) == true);
+ assert(static_cast<bool>(other) == true);
+ assert(opt->get() != nullptr);
+ assert(other->get() == nullptr);
+ }
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ {
+ optional<X> opt;
+ optional<int> opt2(42);
+ assert(static_cast<bool>(opt2) == true);
+ try
+ {
+ X::throw_now = true;
+ opt = std::move(opt2);
+ assert(false);
+ }
+ catch (int i)
+ {
+ assert(i == 6);
+ assert(static_cast<bool>(opt) == false);
+ }
+ }
+#endif
+}
OpenPOWER on IntegriCloud