diff options
Diffstat (limited to 'libcxx/test/std/utilities/variant/variant.variant/variant.ctor')
8 files changed, 964 insertions, 0 deletions
diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp new file mode 100644 index 00000000000..b9ea61046b4 --- /dev/null +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/T.pass.cpp @@ -0,0 +1,112 @@ +// -*- 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> constexpr variant(T&&) noexcept(see below); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "test_convertible.hpp" +#include "test_macros.h" +#include "variant_test_helpers.hpp" + +struct Dummy { + Dummy() = default; +}; + +struct ThrowsT { + ThrowsT(int) noexcept(false) {} +}; + +struct NoThrowT { + NoThrowT(int) noexcept(true) {} +}; + +void test_T_ctor_noexcept() { + { + using V = std::variant<Dummy, NoThrowT>; + static_assert(std::is_nothrow_constructible<V, int>::value, ""); + } + { + using V = std::variant<Dummy, ThrowsT>; + static_assert(!std::is_nothrow_constructible<V, int>::value, ""); + } +} + +void test_T_ctor_sfinae() { + { + using V = std::variant<long, unsigned>; + static_assert(!std::is_constructible<V, int>::value, "ambiguous"); + } + { + using V = std::variant<std::string, std::string>; + static_assert(!std::is_constructible<V, const char *>::value, "ambiguous"); + } + { + using V = std::variant<std::string, void *>; + static_assert(!std::is_constructible<V, int>::value, + "no matching constructor"); + } +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int, int &&>; + static_assert(!std::is_constructible<V, int>::value, "ambiguous"); + } + { + using V = std::variant<int, int const &>; + static_assert(!std::is_constructible<V, int>::value, "ambiguous"); + } +#endif +} + +void test_T_ctor_basic() { + { + constexpr std::variant<int> v(42); + static_assert(v.index() == 0, ""); + static_assert(std::get<0>(v) == 42, ""); + } + { + constexpr std::variant<int, long> v(42l); + static_assert(v.index() == 1, ""); + static_assert(std::get<1>(v) == 42, ""); + } +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int const &, int &&, long>; + static_assert(std::is_convertible<int &, V>::value, "must be implicit"); + int x = 42; + V v(x); + assert(v.index() == 0); + assert(&std::get<0>(v) == &x); + } + { + using V = std::variant<int const &, int &&, long>; + static_assert(std::is_convertible<int, V>::value, "must be implicit"); + int x = 42; + V v(std::move(x)); + assert(v.index() == 1); + assert(&std::get<1>(v) == &x); + } +#endif +} + +int main() { + test_T_ctor_basic(); + test_T_ctor_noexcept(); + test_T_ctor_sfinae(); +} diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp new file mode 100644 index 00000000000..90f4f2c5655 --- /dev/null +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp @@ -0,0 +1,137 @@ +// -*- 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; + +// variant(variant const&); + +#include <cassert> +#include <type_traits> +#include <variant> + +#include "test_macros.h" + +struct NonT { + NonT(int v) : value(v) {} + NonT(NonT const &o) : value(o.value) {} + int value; +}; +static_assert(!std::is_trivially_copy_constructible<NonT>::value, ""); + +struct NoCopy { + NoCopy(NoCopy const &) = delete; +}; + +struct MoveOnly { + MoveOnly(MoveOnly const &) = delete; + MoveOnly(MoveOnly &&) = default; +}; + +struct MoveOnlyNT { + MoveOnlyNT(MoveOnlyNT const &) = delete; + MoveOnlyNT(MoveOnlyNT &&) {} +}; + +#ifndef TEST_HAS_NO_EXCEPTIONS +struct MakeEmptyT { + static int alive; + MakeEmptyT() { ++alive; } + MakeEmptyT(MakeEmptyT const &) { + ++alive; + // Don't throw from the copy constructor since variant's assignment + // operator performs a copy before committing to the assignment. + } + MakeEmptyT(MakeEmptyT &&) { throw 42; } + MakeEmptyT &operator=(MakeEmptyT const &) { throw 42; } + MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; } + ~MakeEmptyT() { --alive; } +}; + +int MakeEmptyT::alive = 0; + +template <class Variant> void makeEmpty(Variant &v) { + Variant v2(std::in_place_type<MakeEmptyT>); + try { + v = v2; + assert(false); + } catch (...) { + assert(v.valueless_by_exception()); + } +} +#endif // TEST_HAS_NO_EXCEPTIONS + +void test_copy_ctor_sfinae() { + { + using V = std::variant<int, long>; + static_assert(std::is_copy_constructible<V>::value, ""); + } + { + using V = std::variant<int, NoCopy>; + static_assert(!std::is_copy_constructible<V>::value, ""); + } + { + using V = std::variant<int, MoveOnly>; + static_assert(!std::is_copy_constructible<V>::value, ""); + } + { + using V = std::variant<int, MoveOnlyNT>; + static_assert(!std::is_copy_constructible<V>::value, ""); + } +} + +void test_copy_ctor_basic() { + { + std::variant<int> v(std::in_place_index<0>, 42); + std::variant<int> v2 = v; + assert(v2.index() == 0); + assert(std::get<0>(v2) == 42); + } + { + std::variant<int, long> v(std::in_place_index<1>, 42); + std::variant<int, long> v2 = v; + assert(v2.index() == 1); + assert(std::get<1>(v2) == 42); + } + { + std::variant<NonT> v(std::in_place_index<0>, 42); + assert(v.index() == 0); + std::variant<NonT> v2(v); + assert(v2.index() == 0); + assert(std::get<0>(v2).value == 42); + } + { + std::variant<int, NonT> v(std::in_place_index<1>, 42); + assert(v.index() == 1); + std::variant<int, NonT> v2(v); + assert(v2.index() == 1); + assert(std::get<1>(v2).value == 42); + } +} + +void test_copy_ctor_valueless_by_exception() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using V = std::variant<int, MakeEmptyT>; + V v1; + makeEmpty(v1); + V const &cv1 = v1; + V v(cv1); + assert(v.valueless_by_exception()); +#endif +} + +int main() { + test_copy_ctor_basic(); + test_copy_ctor_valueless_by_exception(); + test_copy_ctor_sfinae(); +} diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/default.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/default.pass.cpp new file mode 100644 index 00000000000..124260bfcbf --- /dev/null +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/default.pass.cpp @@ -0,0 +1,112 @@ +// -*- 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; + +// constexpr variant() noexcept(see below); + +#include <cassert> +#include <type_traits> +#include <variant> + +#include "test_macros.h" +#include "variant_test_helpers.hpp" + +struct NonDefaultConstructible { + NonDefaultConstructible(int) {} +}; + +struct NotNoexcept { + NotNoexcept() noexcept(false) {} +}; + +#ifndef TEST_HAS_NO_EXCEPTIONS +struct DefaultCtorThrows { + DefaultCtorThrows() { throw 42; } +}; +#endif + +void test_default_ctor_sfinae() { + { + using V = std::variant<std::monostate, int>; + static_assert(std::is_default_constructible<V>::value, ""); + } + { + using V = std::variant<NonDefaultConstructible, int>; + static_assert(!std::is_default_constructible<V>::value, ""); + } +#if !defined(TEST_VARIANT_HAS_NO_REFERENCES) + { + using V = std::variant<int &, int>; + static_assert(!std::is_default_constructible<V>::value, ""); + } +#endif +} + +void test_default_ctor_noexcept() { + { + using V = std::variant<int>; + static_assert(std::is_nothrow_default_constructible<V>::value, ""); + } + { + using V = std::variant<NotNoexcept>; + static_assert(!std::is_nothrow_default_constructible<V>::value, ""); + } +} + +void test_default_ctor_throws() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using V = std::variant<DefaultCtorThrows, int>; + try { + V v; + assert(false); + } catch (int const &ex) { + assert(ex == 42); + } catch (...) { + assert(false); + } +#endif +} + +void test_default_ctor_basic() { + { + std::variant<int> v; + assert(v.index() == 0); + assert(std::get<0>(v) == 0); + } + { + std::variant<int, long> v; + assert(v.index() == 0); + assert(std::get<0>(v) == 0); + } + { + using V = std::variant<int, long>; + constexpr V v; + static_assert(v.index() == 0, ""); + static_assert(std::get<0>(v) == 0, ""); + } + { + using V = std::variant<int, long>; + constexpr V v; + static_assert(v.index() == 0, ""); + static_assert(std::get<0>(v) == 0, ""); + } +} + +int main() { + test_default_ctor_basic(); + test_default_ctor_sfinae(); + test_default_ctor_noexcept(); + test_default_ctor_throws(); +} diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_args.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_args.pass.cpp new file mode 100644 index 00000000000..18115722f8d --- /dev/null +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_args.pass.cpp @@ -0,0 +1,103 @@ +// -*- 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 <size_t I, class ...Args> +// constexpr explicit variant(in_place_index_t<I>, Args&&...); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "test_convertible.hpp" +#include "test_macros.h" + +void test_ctor_sfinae() { + { + using V = std::variant<int>; + static_assert( + std::is_constructible<V, std::in_place_index_t<0>, int>::value, ""); + static_assert(!test_convertible<V, std::in_place_index_t<0>, int>(), ""); + } + { + using V = std::variant<int, long, long long>; + static_assert( + std::is_constructible<V, std::in_place_index_t<1>, int>::value, ""); + static_assert(!test_convertible<V, std::in_place_index_t<1>, int>(), ""); + } + { + using V = std::variant<int, long, int *>; + static_assert( + std::is_constructible<V, std::in_place_index_t<2>, int *>::value, ""); + static_assert(!test_convertible<V, std::in_place_index_t<2>, int *>(), ""); + } + { // args not convertible to type + using V = std::variant<int, long, int *>; + static_assert( + !std::is_constructible<V, std::in_place_index_t<0>, int *>::value, ""); + static_assert(!test_convertible<V, std::in_place_index_t<0>, int *>(), ""); + } + { // index not in variant + using V = std::variant<int, long, int *>; + static_assert( + !std::is_constructible<V, std::in_place_index_t<3>, int>::value, ""); + static_assert(!test_convertible<V, std::in_place_index_t<3>, int>(), ""); + } +} + +void test_ctor_basic() { + { + constexpr std::variant<int> v(std::in_place_index<0>, 42); + static_assert(v.index() == 0, ""); + static_assert(std::get<0>(v) == 42, ""); + } + { + constexpr std::variant<int, long, long> v(std::in_place_index<1>, 42); + static_assert(v.index() == 1, ""); + static_assert(std::get<1>(v) == 42, ""); + } + { + constexpr std::variant<int, const int, long> v(std::in_place_index<1>, 42); + static_assert(v.index() == 1, ""); + static_assert(std::get<1>(v) == 42, ""); + } + { + using V = std::variant<const int, volatile int, int>; + int x = 42; + V v(std::in_place_index<0>, x); + assert(v.index() == 0); + assert(std::get<0>(v) == x); + } + { + using V = std::variant<const int, volatile int, int>; + int x = 42; + V v(std::in_place_index<1>, x); + assert(v.index() == 1); + assert(std::get<1>(v) == x); + } + { + using V = std::variant<const int, volatile int, int>; + int x = 42; + V v(std::in_place_index<2>, x); + assert(v.index() == 2); + assert(std::get<2>(v) == x); + } +} + +int main() { + test_ctor_basic(); + test_ctor_sfinae(); +} diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_init_list_args.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_init_list_args.pass.cpp new file mode 100644 index 00000000000..608cdf9d6ef --- /dev/null +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/in_place_index_init_list_args.pass.cpp @@ -0,0 +1,103 @@ +// -*- 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 <size_t I, class Up, class ...Args> +// constexpr explicit +// variant(in_place_index_t<I>, initializer_list<Up>, Args&&...); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "test_convertible.hpp" +#include "test_macros.h" + +struct InitList { + std::size_t size; + constexpr InitList(std::initializer_list<int> il) : size(il.size()) {} +}; + +struct InitListArg { + std::size_t size; + int value; + constexpr InitListArg(std::initializer_list<int> il, int v) + : size(il.size()), value(v) {} +}; + +void test_ctor_sfinae() { + using IL = std::initializer_list<int>; + { // just init list + using V = std::variant<InitList, InitListArg, int>; + static_assert(std::is_constructible<V, std::in_place_index_t<0>, IL>::value, + ""); + static_assert(!test_convertible<V, std::in_place_index_t<0>, IL>(), ""); + } + { // too many arguments + using V = std::variant<InitList, InitListArg, int>; + static_assert( + !std::is_constructible<V, std::in_place_index_t<0>, IL, int>::value, + ""); + static_assert(!test_convertible<V, std::in_place_index_t<0>, IL, int>(), + ""); + } + { // too few arguments + using V = std::variant<InitList, InitListArg, int>; + static_assert( + !std::is_constructible<V, std::in_place_index_t<1>, IL>::value, ""); + static_assert(!test_convertible<V, std::in_place_index_t<1>, IL>(), ""); + } + { // init list and arguments + using V = std::variant<InitList, InitListArg, int>; + static_assert( + std::is_constructible<V, std::in_place_index_t<1>, IL, int>::value, ""); + static_assert(!test_convertible<V, std::in_place_index_t<1>, IL, int>(), + ""); + } + { // not constructible from arguments + using V = std::variant<InitList, InitListArg, int>; + static_assert( + !std::is_constructible<V, std::in_place_index_t<2>, IL>::value, ""); + static_assert(!test_convertible<V, std::in_place_index_t<2>, IL>(), ""); + } +} + +void test_ctor_basic() { + { + constexpr std::variant<InitList, InitListArg, InitList> v( + std::in_place_index<0>, {1, 2, 3}); + static_assert(v.index() == 0, ""); + static_assert(std::get<0>(v).size == 3, ""); + } + { + constexpr std::variant<InitList, InitListArg, InitList> v( + std::in_place_index<2>, {1, 2, 3}); + static_assert(v.index() == 2, ""); + static_assert(std::get<2>(v).size == 3, ""); + } + { + constexpr std::variant<InitList, InitListArg, InitListArg> v( + std::in_place_index<1>, {1, 2, 3, 4}, 42); + static_assert(v.index() == 1, ""); + static_assert(std::get<1>(v).size == 4, ""); + static_assert(std::get<1>(v).value == 42, ""); + } +} + +int main() { + test_ctor_basic(); + test_ctor_sfinae(); +} diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_args.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_args.pass.cpp new file mode 100644 index 00000000000..a023f02bad6 --- /dev/null +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_args.pass.cpp @@ -0,0 +1,113 @@ +// -*- 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 Tp, class ...Args> +// constexpr explicit variant(in_place_type_t<Tp>, Args&&...); + +#include <cassert> +#include <type_traits> +#include <variant> + +#include "test_convertible.hpp" +#include "test_macros.h" + +void test_ctor_sfinae() { + { + using V = std::variant<int>; + static_assert( + std::is_constructible<V, std::in_place_type_t<int>, int>::value, ""); + static_assert(!test_convertible<V, std::in_place_type_t<int>, int>(), ""); + } + { + using V = std::variant<int, long, long long>; + static_assert( + std::is_constructible<V, std::in_place_type_t<long>, int>::value, ""); + static_assert(!test_convertible<V, std::in_place_type_t<long>, int>(), ""); + } + { + using V = std::variant<int, long, int *>; + static_assert( + std::is_constructible<V, std::in_place_type_t<int *>, int *>::value, + ""); + static_assert(!test_convertible<V, std::in_place_type_t<int *>, int *>(), + ""); + } + { // duplicate type + using V = std::variant<int, long, int>; + static_assert( + !std::is_constructible<V, std::in_place_type_t<int>, int>::value, ""); + static_assert(!test_convertible<V, std::in_place_type_t<int>, int>(), ""); + } + { // args not convertible to type + using V = std::variant<int, long, int *>; + static_assert( + !std::is_constructible<V, std::in_place_type_t<int>, int *>::value, ""); + static_assert(!test_convertible<V, std::in_place_type_t<int>, int *>(), ""); + } + { // type not in variant + using V = std::variant<int, long, int *>; + static_assert( + !std::is_constructible<V, std::in_place_type_t<long long>, int>::value, + ""); + static_assert(!test_convertible<V, std::in_place_type_t<long long>, int>(), + ""); + } +} + +void test_ctor_basic() { + { + constexpr std::variant<int> v(std::in_place_type<int>, 42); + static_assert(v.index() == 0, ""); + static_assert(std::get<0>(v) == 42, ""); + } + { + constexpr std::variant<int, long> v(std::in_place_type<long>, 42); + static_assert(v.index() == 1, ""); + static_assert(std::get<1>(v) == 42, ""); + } + { + constexpr std::variant<int, const int, long> v( + std::in_place_type<const int>, 42); + static_assert(v.index() == 1, ""); + static_assert(std::get<1>(v) == 42, ""); + } + { + using V = std::variant<const int, volatile int, int>; + int x = 42; + V v(std::in_place_type<const int>, x); + assert(v.index() == 0); + assert(std::get<0>(v) == x); + } + { + using V = std::variant<const int, volatile int, int>; + int x = 42; + V v(std::in_place_type<volatile int>, x); + assert(v.index() == 1); + assert(std::get<1>(v) == x); + } + { + using V = std::variant<const int, volatile int, int>; + int x = 42; + V v(std::in_place_type<int>, x); + assert(v.index() == 2); + assert(std::get<2>(v) == x); + } +} + +int main() { + test_ctor_basic(); + test_ctor_sfinae(); +} diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_init_list_args.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_init_list_args.pass.cpp new file mode 100644 index 00000000000..e151572c466 --- /dev/null +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/in_place_type_init_list_args.pass.cpp @@ -0,0 +1,110 @@ +// -*- 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 Tp, class Up, class ...Args> +// constexpr explicit +// variant(in_place_type_t<Tp>, initializer_list<Up>, Args&&...); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "test_convertible.hpp" +#include "test_macros.h" + +struct InitList { + std::size_t size; + constexpr InitList(std::initializer_list<int> il) : size(il.size()) {} +}; + +struct InitListArg { + std::size_t size; + int value; + constexpr InitListArg(std::initializer_list<int> il, int v) + : size(il.size()), value(v) {} +}; + +void test_ctor_sfinae() { + using IL = std::initializer_list<int>; + { // just init list + using V = std::variant<InitList, InitListArg, int>; + static_assert( + std::is_constructible<V, std::in_place_type_t<InitList>, IL>::value, + ""); + static_assert(!test_convertible<V, std::in_place_type_t<InitList>, IL>(), + ""); + } + { // too many arguments + using V = std::variant<InitList, InitListArg, int>; + static_assert(!std::is_constructible<V, std::in_place_type_t<InitList>, IL, + int>::value, + ""); + static_assert( + !test_convertible<V, std::in_place_type_t<InitList>, IL, int>(), ""); + } + { // too few arguments + using V = std::variant<InitList, InitListArg, int>; + static_assert( + !std::is_constructible<V, std::in_place_type_t<InitListArg>, IL>::value, + ""); + static_assert(!test_convertible<V, std::in_place_type_t<InitListArg>, IL>(), + ""); + } + { // init list and arguments + using V = std::variant<InitList, InitListArg, int>; + static_assert(std::is_constructible<V, std::in_place_type_t<InitListArg>, + IL, int>::value, + ""); + static_assert( + !test_convertible<V, std::in_place_type_t<InitListArg>, IL, int>(), ""); + } + { // not constructible from arguments + using V = std::variant<InitList, InitListArg, int>; + static_assert( + !std::is_constructible<V, std::in_place_type_t<int>, IL>::value, ""); + static_assert(!test_convertible<V, std::in_place_type_t<int>, IL>(), ""); + } + { // duplicate types in variant + using V = std::variant<InitListArg, InitListArg, int>; + static_assert(!std::is_constructible<V, std::in_place_type_t<InitListArg>, + IL, int>::value, + ""); + static_assert( + !test_convertible<V, std::in_place_type_t<InitListArg>, IL, int>(), ""); + } +} + +void test_ctor_basic() { + { + constexpr std::variant<InitList, InitListArg> v( + std::in_place_type<InitList>, {1, 2, 3}); + static_assert(v.index() == 0, ""); + static_assert(std::get<0>(v).size == 3, ""); + } + { + constexpr std::variant<InitList, InitListArg> v( + std::in_place_type<InitListArg>, {1, 2, 3, 4}, 42); + static_assert(v.index() == 1, ""); + static_assert(std::get<1>(v).size == 4, ""); + static_assert(std::get<1>(v).value == 42, ""); + } +} + +int main() { + test_ctor_basic(); + test_ctor_sfinae(); +} diff --git a/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp new file mode 100644 index 00000000000..dcc973f074f --- /dev/null +++ b/libcxx/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp @@ -0,0 +1,174 @@ +// -*- 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; + +// variant(variant&&) noexcept(see below); + +#include <cassert> +#include <string> +#include <type_traits> +#include <variant> + +#include "test_macros.h" + +struct ThrowsMove { + ThrowsMove(ThrowsMove &&) noexcept(false) {} +}; + +struct NoCopy { + NoCopy(NoCopy const &) = delete; +}; + +struct MoveOnly { + int value; + MoveOnly(int v) : value(v) {} + MoveOnly(MoveOnly const &) = delete; + MoveOnly(MoveOnly &&) = default; +}; + +struct MoveOnlyNT { + int value; + MoveOnlyNT(int v) : value(v) {} + MoveOnlyNT(MoveOnlyNT const &) = delete; + MoveOnlyNT(MoveOnlyNT &&other) : value(other.value) { other.value = -1; } +}; + +#ifndef TEST_HAS_NO_EXCEPTIONS +struct MakeEmptyT { + static int alive; + MakeEmptyT() { ++alive; } + MakeEmptyT(MakeEmptyT const &) { + ++alive; + // Don't throw from the copy constructor since variant's assignment + // operator performs a copy before committing to the assignment. + } + MakeEmptyT(MakeEmptyT &&) { throw 42; } + MakeEmptyT &operator=(MakeEmptyT const &) { throw 42; } + MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; } + ~MakeEmptyT() { --alive; } +}; + +int MakeEmptyT::alive = 0; + +template <class Variant> void makeEmpty(Variant &v) { + Variant v2(std::in_place_type<MakeEmptyT>); + try { + v = v2; + assert(false); + } catch (...) { + assert(v.valueless_by_exception()); + } +} +#endif // TEST_HAS_NO_EXCEPTIONS + +void test_move_noexcept() { + { + using V = std::variant<int, long>; + static_assert(std::is_nothrow_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, MoveOnly>; + static_assert(std::is_nothrow_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, MoveOnlyNT>; + static_assert(!std::is_nothrow_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, ThrowsMove>; + static_assert(!std::is_nothrow_move_constructible<V>::value, ""); + } +} + +void test_move_ctor_sfinae() { + { + using V = std::variant<int, long>; + static_assert(std::is_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, MoveOnly>; + static_assert(std::is_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, MoveOnlyNT>; + static_assert(std::is_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, NoCopy>; + static_assert(!std::is_move_constructible<V>::value, ""); + } +} + +void test_move_ctor_basic() { + { + std::variant<int> v(std::in_place_index<0>, 42); + std::variant<int> v2 = std::move(v); + assert(v2.index() == 0); + assert(std::get<0>(v2) == 42); + } + { + std::variant<int, long> v(std::in_place_index<1>, 42); + std::variant<int, long> v2 = std::move(v); + assert(v2.index() == 1); + assert(std::get<1>(v2) == 42); + } + { + std::variant<MoveOnly> v(std::in_place_index<0>, 42); + assert(v.index() == 0); + std::variant<MoveOnly> v2(std::move(v)); + assert(v2.index() == 0); + assert(std::get<0>(v2).value == 42); + } + { + std::variant<int, MoveOnly> v(std::in_place_index<1>, 42); + assert(v.index() == 1); + std::variant<int, MoveOnly> v2(std::move(v)); + assert(v2.index() == 1); + assert(std::get<1>(v2).value == 42); + } + { + std::variant<MoveOnlyNT> v(std::in_place_index<0>, 42); + assert(v.index() == 0); + std::variant<MoveOnlyNT> v2(std::move(v)); + assert(v2.index() == 0); + assert(std::get<0>(v).value == -1); + assert(std::get<0>(v2).value == 42); + } + { + std::variant<int, MoveOnlyNT> v(std::in_place_index<1>, 42); + assert(v.index() == 1); + std::variant<int, MoveOnlyNT> v2(std::move(v)); + assert(v2.index() == 1); + assert(std::get<1>(v).value == -1); + assert(std::get<1>(v2).value == 42); + } +} + +void test_move_ctor_valueless_by_exception() { +#ifndef TEST_HAS_NO_EXCEPTIONS + using V = std::variant<int, MakeEmptyT>; + V v1; + makeEmpty(v1); + V v(std::move(v1)); + assert(v.valueless_by_exception()); +#endif +} + +int main() { + test_move_ctor_basic(); + test_move_ctor_valueless_by_exception(); + test_move_noexcept(); + test_move_ctor_sfinae(); +} |