diff options
Diffstat (limited to 'test/libcxx/utilities/variant')
5 files changed, 698 insertions, 0 deletions
diff --git a/test/libcxx/utilities/variant/variant.variant/variant.assign/copy.pass.cpp b/test/libcxx/utilities/variant/variant.variant/variant.assign/copy.pass.cpp new file mode 100644 index 0000000000000..a94aa2f78299b --- /dev/null +++ b/test/libcxx/utilities/variant/variant.variant/variant.assign/copy.pass.cpp @@ -0,0 +1,208 @@ +// -*- 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 + +// Clang 3.8 doesn't generate constexpr special members correctly. +// XFAIL: clang-3.8, apple-clang-7, apple-clang-8 + +// <variant> + +// template <class ...Types> class variant; + +// variant& operator=(variant const&); + +#include <type_traits> +#include <variant> + +#include "test_macros.h" + +struct NTCopyAssign { + constexpr NTCopyAssign(int v) : value(v) {} + NTCopyAssign(const NTCopyAssign &) = default; + NTCopyAssign(NTCopyAssign &&) = default; + NTCopyAssign &operator=(const NTCopyAssign &that) { + value = that.value; + return *this; + }; + NTCopyAssign &operator=(NTCopyAssign &&) = delete; + int value; +}; + +static_assert(!std::is_trivially_copy_assignable<NTCopyAssign>::value, ""); +static_assert(std::is_copy_assignable<NTCopyAssign>::value, ""); + +struct TCopyAssign { + constexpr TCopyAssign(int v) : value(v) {} + TCopyAssign(const TCopyAssign &) = default; + TCopyAssign(TCopyAssign &&) = default; + TCopyAssign &operator=(const TCopyAssign &) = default; + TCopyAssign &operator=(TCopyAssign &&) = delete; + int value; +}; + +static_assert(std::is_trivially_copy_assignable<TCopyAssign>::value, ""); + +struct TCopyAssignNTMoveAssign { + constexpr TCopyAssignNTMoveAssign(int v) : value(v) {} + TCopyAssignNTMoveAssign(const TCopyAssignNTMoveAssign &) = default; + TCopyAssignNTMoveAssign(TCopyAssignNTMoveAssign &&) = default; + TCopyAssignNTMoveAssign &operator=(const TCopyAssignNTMoveAssign &) = default; + TCopyAssignNTMoveAssign &operator=(TCopyAssignNTMoveAssign &&that) { + value = that.value; + that.value = -1; + return *this; + } + int value; +}; + +static_assert(std::is_trivially_copy_assignable_v<TCopyAssignNTMoveAssign>); + +void test_copy_assignment_sfinae() { + { + using V = std::variant<int, long>; + static_assert(std::is_trivially_copy_assignable<V>::value, ""); + } + { + using V = std::variant<int, NTCopyAssign>; + static_assert(!std::is_trivially_copy_assignable<V>::value, ""); + static_assert(std::is_copy_assignable<V>::value, ""); + } + { + using V = std::variant<int, TCopyAssign>; + static_assert(std::is_trivially_copy_assignable<V>::value, ""); + } + { + using V = std::variant<int, TCopyAssignNTMoveAssign>; + static_assert(std::is_trivially_copy_assignable<V>::value, ""); + } +} + +template <typename T> struct Result { size_t index; T value; }; + +void test_copy_assignment_same_index() { + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int>; + V v(43); + V v2(42); + v = v2; + return {v.index(), std::get<0>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 0); + static_assert(result.value == 42); + } + { + struct { + constexpr Result<long> operator()() const { + using V = std::variant<int, long, unsigned>; + V v(43l); + V v2(42l); + v = v2; + return {v.index(), std::get<1>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42l); + } + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int, TCopyAssign, unsigned>; + V v(std::in_place_type<TCopyAssign>, 43); + V v2(std::in_place_type<TCopyAssign>, 42); + v = v2; + return {v.index(), std::get<1>(v).value}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42); + } + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int, TCopyAssignNTMoveAssign, unsigned>; + V v(std::in_place_type<TCopyAssignNTMoveAssign>, 43); + V v2(std::in_place_type<TCopyAssignNTMoveAssign>, 42); + v = v2; + return {v.index(), std::get<1>(v).value}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42); + } +} + +void test_copy_assignment_different_index() { + { + struct { + constexpr Result<long> operator()() const { + using V = std::variant<int, long, unsigned>; + V v(43); + V v2(42l); + v = v2; + return {v.index(), std::get<1>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42l); + } + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int, TCopyAssign, unsigned>; + V v(std::in_place_type<unsigned>, 43); + V v2(std::in_place_type<TCopyAssign>, 42); + v = v2; + return {v.index(), std::get<1>(v).value}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42); + } +} + +template <size_t NewIdx, class ValueType> +constexpr bool test_constexpr_assign_extension_imp( + std::variant<long, void*, int>&& v, ValueType&& new_value) +{ + const std::variant<long, void*, int> cp( + std::forward<ValueType>(new_value)); + v = cp; + return v.index() == NewIdx && + std::get<NewIdx>(v) == std::get<NewIdx>(cp); +} + +void test_constexpr_copy_assignment_extension() { +#ifdef _LIBCPP_VERSION + using V = std::variant<long, void*, int>; + static_assert(std::is_trivially_copyable<V>::value, ""); + static_assert(std::is_trivially_copy_assignable<V>::value, ""); + static_assert(test_constexpr_assign_extension_imp<0>(V(42l), 101l), ""); + static_assert(test_constexpr_assign_extension_imp<0>(V(nullptr), 101l), ""); + static_assert(test_constexpr_assign_extension_imp<1>(V(42l), nullptr), ""); + static_assert(test_constexpr_assign_extension_imp<2>(V(42l), 101), ""); +#endif +} + +int main() { + test_copy_assignment_same_index(); + test_copy_assignment_different_index(); + test_copy_assignment_sfinae(); + test_constexpr_copy_assignment_extension(); +} diff --git a/test/libcxx/utilities/variant/variant.variant/variant.assign/move.pass.cpp b/test/libcxx/utilities/variant/variant.variant/variant.assign/move.pass.cpp new file mode 100644 index 0000000000000..a3d92472dd5e9 --- /dev/null +++ b/test/libcxx/utilities/variant/variant.variant/variant.assign/move.pass.cpp @@ -0,0 +1,197 @@ +// -*- 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 + +// Clang 3.8 doesn't generate constexpr special members correctly. +// XFAIL: clang-3.8, apple-clang-7, apple-clang-8 + + +// <variant> + +// template <class ...Types> class variant; + +// variant& operator=(variant&&) noexcept(see below); + +#include <type_traits> +#include <variant> + +#include "test_macros.h" + +struct NTMoveAssign { + constexpr NTMoveAssign(int v) : value(v) {} + NTMoveAssign(const NTMoveAssign &) = default; + NTMoveAssign(NTMoveAssign &&) = default; + NTMoveAssign &operator=(const NTMoveAssign &that) = default; + NTMoveAssign &operator=(NTMoveAssign &&that) { + value = that.value; + that.value = -1; + return *this; + }; + int value; +}; + +static_assert(!std::is_trivially_move_assignable<NTMoveAssign>::value, ""); +static_assert(std::is_move_assignable<NTMoveAssign>::value, ""); + +struct TMoveAssign { + constexpr TMoveAssign(int v) : value(v) {} + TMoveAssign(const TMoveAssign &) = delete; + TMoveAssign(TMoveAssign &&) = default; + TMoveAssign &operator=(const TMoveAssign &) = delete; + TMoveAssign &operator=(TMoveAssign &&) = default; + int value; +}; + +static_assert(std::is_trivially_move_assignable<TMoveAssign>::value, ""); + +struct TMoveAssignNTCopyAssign { + constexpr TMoveAssignNTCopyAssign(int v) : value(v) {} + TMoveAssignNTCopyAssign(const TMoveAssignNTCopyAssign &) = default; + TMoveAssignNTCopyAssign(TMoveAssignNTCopyAssign &&) = default; + TMoveAssignNTCopyAssign &operator=(const TMoveAssignNTCopyAssign &that) { + value = that.value; + return *this; + } + TMoveAssignNTCopyAssign &operator=(TMoveAssignNTCopyAssign &&) = default; + int value; +}; + +static_assert(std::is_trivially_move_assignable_v<TMoveAssignNTCopyAssign>); + +void test_move_assignment_sfinae() { + { + using V = std::variant<int, long>; + static_assert(std::is_trivially_move_assignable<V>::value, ""); + } + { + using V = std::variant<int, NTMoveAssign>; + static_assert(!std::is_trivially_move_assignable<V>::value, ""); + static_assert(std::is_move_assignable<V>::value, ""); + } + { + using V = std::variant<int, TMoveAssign>; + static_assert(std::is_trivially_move_assignable<V>::value, ""); + } + { + using V = std::variant<int, TMoveAssignNTCopyAssign>; + static_assert(std::is_trivially_move_assignable<V>::value, ""); + } +} + +template <typename T> struct Result { size_t index; T value; }; + +void test_move_assignment_same_index() { + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int>; + V v(43); + V v2(42); + v = std::move(v2); + return {v.index(), std::get<0>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 0); + static_assert(result.value == 42); + } + { + struct { + constexpr Result<long> operator()() const { + using V = std::variant<int, long, unsigned>; + V v(43l); + V v2(42l); + v = std::move(v2); + return {v.index(), std::get<1>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42l); + } + { + struct { + constexpr Result<int> operator()() const { + using V = std::variant<int, TMoveAssign, unsigned>; + V v(std::in_place_type<TMoveAssign>, 43); + V v2(std::in_place_type<TMoveAssign>, 42); + v = std::move(v2); + return {v.index(), std::get<1>(v).value}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42); + } +} + +void test_move_assignment_different_index() { + { + struct { + constexpr Result<long> operator()() const { + using V = std::variant<int, long, unsigned>; + V v(43); + V v2(42l); + v = std::move(v2); + return {v.index(), std::get<1>(v)}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42l); + } + { + struct { + constexpr Result<long> operator()() const { + using V = std::variant<int, TMoveAssign, unsigned>; + V v(std::in_place_type<unsigned>, 43); + V v2(std::in_place_type<TMoveAssign>, 42); + v = std::move(v2); + return {v.index(), std::get<1>(v).value}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42); + } +} + + +template <size_t NewIdx, class ValueType> +constexpr bool test_constexpr_assign_extension_imp( + std::variant<long, void*, int>&& v, ValueType&& new_value) +{ + std::variant<long, void*, int> v2( + std::forward<ValueType>(new_value)); + const auto cp = v2; + v = std::move(v2); + return v.index() == NewIdx && + std::get<NewIdx>(v) == std::get<NewIdx>(cp); +} + +void test_constexpr_move_assignment_extension() { +#ifdef _LIBCPP_VERSION + using V = std::variant<long, void*, int>; + static_assert(std::is_trivially_copyable<V>::value, ""); + static_assert(std::is_trivially_move_assignable<V>::value, ""); + static_assert(test_constexpr_assign_extension_imp<0>(V(42l), 101l), ""); + static_assert(test_constexpr_assign_extension_imp<0>(V(nullptr), 101l), ""); + static_assert(test_constexpr_assign_extension_imp<1>(V(42l), nullptr), ""); + static_assert(test_constexpr_assign_extension_imp<2>(V(42l), 101), ""); +#endif +} + +int main() { + test_move_assignment_same_index(); + test_move_assignment_different_index(); + test_move_assignment_sfinae(); + test_constexpr_move_assignment_extension(); +} diff --git a/test/libcxx/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp b/test/libcxx/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp new file mode 100644 index 0000000000000..59c4330505907 --- /dev/null +++ b/test/libcxx/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp @@ -0,0 +1,120 @@ +// -*- 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 <type_traits> +#include <variant> + +#include "test_macros.h" + +struct NTCopy { + constexpr NTCopy(int v) : value(v) {} + NTCopy(const NTCopy &that) : value(that.value) {} + NTCopy(NTCopy &&) = delete; + int value; +}; + +static_assert(!std::is_trivially_copy_constructible<NTCopy>::value, ""); +static_assert(std::is_copy_constructible<NTCopy>::value, ""); + +struct TCopy { + constexpr TCopy(int v) : value(v) {} + TCopy(TCopy const &) = default; + TCopy(TCopy &&) = delete; + int value; +}; + +static_assert(std::is_trivially_copy_constructible<TCopy>::value, ""); + +struct TCopyNTMove { + constexpr TCopyNTMove(int v) : value(v) {} + TCopyNTMove(const TCopyNTMove&) = default; + TCopyNTMove(TCopyNTMove&& that) : value(that.value) { that.value = -1; } + int value; +}; + +static_assert(std::is_trivially_copy_constructible<TCopyNTMove>::value, ""); + +void test_copy_ctor_sfinae() { + { + using V = std::variant<int, long>; + static_assert(std::is_trivially_copy_constructible<V>::value, ""); + } + { + using V = std::variant<int, NTCopy>; + static_assert(!std::is_trivially_copy_constructible<V>::value, ""); + static_assert(std::is_copy_constructible<V>::value, ""); + } + { + using V = std::variant<int, TCopy>; + static_assert(std::is_trivially_copy_constructible<V>::value, ""); + } + { + using V = std::variant<int, TCopyNTMove>; + static_assert(std::is_trivially_copy_constructible<V>::value, ""); + } +} + +void test_copy_ctor_basic() { + { + constexpr std::variant<int> v(std::in_place_index<0>, 42); + static_assert(v.index() == 0); + constexpr std::variant<int> v2 = v; + static_assert(v2.index() == 0); + static_assert(std::get<0>(v2) == 42); + } + { + constexpr std::variant<int, long> v(std::in_place_index<1>, 42); + static_assert(v.index() == 1); + constexpr std::variant<int, long> v2 = v; + static_assert(v2.index() == 1); + static_assert(std::get<1>(v2) == 42); + } + { + constexpr std::variant<TCopy> v(std::in_place_index<0>, 42); + static_assert(v.index() == 0); + constexpr std::variant<TCopy> v2(v); + static_assert(v2.index() == 0); + static_assert(std::get<0>(v2).value == 42); + } + { + constexpr std::variant<int, TCopy> v(std::in_place_index<1>, 42); + static_assert(v.index() == 1); + constexpr std::variant<int, TCopy> v2(v); + static_assert(v2.index() == 1); + static_assert(std::get<1>(v2).value == 42); + } + { + constexpr std::variant<TCopyNTMove> v(std::in_place_index<0>, 42); + static_assert(v.index() == 0); + constexpr std::variant<TCopyNTMove> v2(v); + static_assert(v2.index() == 0); + static_assert(std::get<0>(v2).value == 42); + } + { + constexpr std::variant<int, TCopyNTMove> v(std::in_place_index<1>, 42); + static_assert(v.index() == 1); + constexpr std::variant<int, TCopyNTMove> v2(v); + static_assert(v2.index() == 1); + static_assert(std::get<1>(v2).value == 42); + } +} + +int main() { + test_copy_ctor_basic(); + test_copy_ctor_sfinae(); +} diff --git a/test/libcxx/utilities/variant/variant.variant/variant.ctor/move.pass.cpp b/test/libcxx/utilities/variant/variant.variant/variant.ctor/move.pass.cpp new file mode 100644 index 0000000000000..e67a495d97995 --- /dev/null +++ b/test/libcxx/utilities/variant/variant.variant/variant.ctor/move.pass.cpp @@ -0,0 +1,153 @@ +// -*- 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 <type_traits> +#include <variant> + +#include "test_macros.h" + +struct NTMove { + constexpr NTMove(int v) : value(v) {} + NTMove(const NTMove &) = delete; + NTMove(NTMove &&that) : value(that.value) { that.value = -1; } + int value; +}; + +static_assert(!std::is_trivially_move_constructible<NTMove>::value, ""); +static_assert(std::is_move_constructible<NTMove>::value, ""); + +struct TMove { + constexpr TMove(int v) : value(v) {} + TMove(const TMove &) = delete; + TMove(TMove &&) = default; + int value; +}; + +static_assert(std::is_trivially_move_constructible<TMove>::value, ""); + +struct TMoveNTCopy { + constexpr TMoveNTCopy(int v) : value(v) {} + TMoveNTCopy(const TMoveNTCopy& that) : value(that.value) {} + TMoveNTCopy(TMoveNTCopy&&) = default; + int value; +}; + +static_assert(std::is_trivially_move_constructible<TMoveNTCopy>::value, ""); + +void test_move_ctor_sfinae() { + { + using V = std::variant<int, long>; + static_assert(std::is_trivially_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, NTMove>; + static_assert(!std::is_trivially_move_constructible<V>::value, ""); + static_assert(std::is_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, TMove>; + static_assert(std::is_trivially_move_constructible<V>::value, ""); + } + { + using V = std::variant<int, TMoveNTCopy>; + static_assert(std::is_trivially_move_constructible<V>::value, ""); + } +} + +template <typename T> +struct Result { size_t index; T value; }; + +void test_move_ctor_basic() { + { + struct { + constexpr Result<int> operator()() const { + std::variant<int> v(std::in_place_index<0>, 42); + std::variant<int> v2 = std::move(v); + return {v2.index(), std::get<0>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 0); + static_assert(result.value == 42); + } + { + struct { + constexpr Result<long> operator()() const { + std::variant<int, long> v(std::in_place_index<1>, 42); + std::variant<int, long> v2 = std::move(v); + return {v2.index(), std::get<1>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value == 42); + } + { + struct { + constexpr Result<TMove> operator()() const { + std::variant<TMove> v(std::in_place_index<0>, 42); + std::variant<TMove> v2(std::move(v)); + return {v2.index(), std::get<0>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 0); + static_assert(result.value.value == 42); + } + { + struct { + constexpr Result<TMove> operator()() const { + std::variant<int, TMove> v(std::in_place_index<1>, 42); + std::variant<int, TMove> v2(std::move(v)); + return {v2.index(), std::get<1>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value.value == 42); + } + { + struct { + constexpr Result<TMoveNTCopy> operator()() const { + std::variant<TMoveNTCopy> v(std::in_place_index<0>, 42); + std::variant<TMoveNTCopy> v2(std::move(v)); + return {v2.index(), std::get<0>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 0); + static_assert(result.value.value == 42); + } + { + struct { + constexpr Result<TMoveNTCopy> operator()() const { + std::variant<int, TMoveNTCopy> v(std::in_place_index<1>, 42); + std::variant<int, TMoveNTCopy> v2(std::move(v)); + return {v2.index(), std::get<1>(std::move(v2))}; + } + } test; + constexpr auto result = test(); + static_assert(result.index == 1); + static_assert(result.value.value == 42); + } +} + +int main() { + test_move_ctor_basic(); + test_move_ctor_sfinae(); +} diff --git a/test/libcxx/utilities/variant/version.pass.cpp b/test/libcxx/utilities/variant/version.pass.cpp new file mode 100644 index 0000000000000..1db93e0e9392f --- /dev/null +++ b/test/libcxx/utilities/variant/version.pass.cpp @@ -0,0 +1,20 @@ +//===----------------------------------------------------------------------===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +// <variant> + +#include <variant> + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION not defined +#endif + +int main() +{ +} |