diff options
Diffstat (limited to 'test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp')
-rw-r--r-- | test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp b/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp new file mode 100644 index 000000000000..10022b14aa06 --- /dev/null +++ b/test/std/utilities/variant/variant.variant/variant.assign/T.pass.cpp @@ -0,0 +1,232 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 + +// <variant> + +// template <class ...Types> class variant; + +// template <class T> +// variant& operator=(T&&) noexcept(see below); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "test_macros.h" +#include "variant_test_helpers.hpp" + +namespace MetaHelpers { + +struct Dummy { + Dummy() = default; +}; + +struct ThrowsCtorT { + ThrowsCtorT(int) noexcept(false) {} + ThrowsCtorT &operator=(int) noexcept { return *this; } +}; + +struct ThrowsAssignT { + ThrowsAssignT(int) noexcept {} + ThrowsAssignT &operator=(int) noexcept(false) { return *this; } +}; + +struct NoThrowT { + NoThrowT(int) noexcept {} + NoThrowT &operator=(int) noexcept { return *this; } +}; + +} // namespace MetaHelpers + +namespace RuntimeHelpers { +#ifndef TEST_HAS_NO_EXCEPTIONS + +struct ThrowsCtorT { + int value; + ThrowsCtorT() : value(0) {} + ThrowsCtorT(int) noexcept(false) { throw 42; } + ThrowsCtorT &operator=(int v) noexcept { + value = v; + return *this; + } +}; + +struct ThrowsAssignT { + int value; + ThrowsAssignT() : value(0) {} + ThrowsAssignT(int v) noexcept : value(v) {} + ThrowsAssignT &operator=(int) noexcept(false) { throw 42; } +}; + +struct NoThrowT { + int value; + NoThrowT() : value(0) {} + NoThrowT(int v) noexcept : value(v) {} + NoThrowT &operator=(int v) noexcept { + value = v; + return *this; + } +}; + +#endif // !defined(TEST_HAS_NO_EXCEPTIONS) +} // namespace RuntimeHelpers + +void test_T_assignment_noexcept() { + using namespace MetaHelpers; + { + using V = std::variant<Dummy, NoThrowT>; + static_assert(std::is_nothrow_assignable<V, int>::value, ""); + } + { + using V = std::variant<Dummy, ThrowsCtorT>; + static_assert(!std::is_nothrow_assignable<V, int>::value, ""); + } + { + using V = std::variant<Dummy, ThrowsAssignT>; + static_assert(!std::is_nothrow_assignable<V, int>::value, ""); + } +} + +void test_T_assignment_sfinae() { + { + using V = std::variant<long, unsigned>; + static_assert(!std::is_assignable<V, int>::value, "ambiguous"); + } + { + using V = std::variant<std::string, std::string>; + static_assert(!std::is_assignable<V, const char *>::value, "ambiguous"); + } + { + using V = std::variant<std::string, void *>; + static_assert(!std::is_assignable<V, int>::value, "no matching operator="); + } +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int, int &&>; + static_assert(!std::is_assignable<V, int>::value, "ambiguous"); + } + { + using V = std::variant<int, const int &>; + static_assert(!std::is_assignable<V, int>::value, "ambiguous"); + } +#endif +} + +void test_T_assignment_basic() { + { + std::variant<int> v(43); + v = 42; + assert(v.index() == 0); + assert(std::get<0>(v) == 42); + } + { + std::variant<int, long> v(43l); + v = 42; + assert(v.index() == 0); + assert(std::get<0>(v) == 42); + v = 43l; + assert(v.index() == 1); + assert(std::get<1>(v) == 43); + } +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int &, int &&, long>; + int x = 42; + V v(43l); + v = x; + assert(v.index() == 0); + assert(&std::get<0>(v) == &x); + v = std::move(x); + assert(v.index() == 1); + assert(&std::get<1>(v) == &x); + // 'long' is selected by FUN(const int &) since 'const int &' cannot bind + // to 'int&'. + const int &cx = x; + v = cx; + assert(v.index() == 2); + assert(std::get<2>(v) == 42); + } +#endif +} + +void test_T_assignment_performs_construction() { + using namespace RuntimeHelpers; +#ifndef TEST_HAS_NO_EXCEPTIONS + { + using V = std::variant<std::string, ThrowsCtorT>; + V v(std::in_place_type<std::string>, "hello"); + try { + v = 42; + } catch (...) { /* ... */ + } + assert(v.valueless_by_exception()); + } + { + using V = std::variant<ThrowsAssignT, std::string>; + V v(std::in_place_type<std::string>, "hello"); + v = 42; + assert(v.index() == 0); + assert(std::get<0>(v).value == 42); + } +#endif +} + +void test_T_assignment_performs_assignment() { + using namespace RuntimeHelpers; +#ifndef TEST_HAS_NO_EXCEPTIONS + { + using V = std::variant<ThrowsCtorT>; + V v; + v = 42; + assert(v.index() == 0); + assert(std::get<0>(v).value == 42); + } + { + using V = std::variant<ThrowsCtorT, std::string>; + V v; + v = 42; + assert(v.index() == 0); + assert(std::get<0>(v).value == 42); + } + { + using V = std::variant<ThrowsAssignT>; + V v(100); + try { + v = 42; + assert(false); + } catch (...) { /* ... */ + } + assert(v.index() == 0); + assert(std::get<0>(v).value == 100); + } + { + using V = std::variant<std::string, ThrowsAssignT>; + V v(100); + try { + v = 42; + assert(false); + } catch (...) { /* ... */ + } + assert(v.index() == 1); + assert(std::get<1>(v).value == 100); + } +#endif +} + +int main() { + test_T_assignment_basic(); + test_T_assignment_performs_construction(); + test_T_assignment_performs_assignment(); + test_T_assignment_noexcept(); + test_T_assignment_sfinae(); +} |