| // { dg-do compile { target c++17 } } |
| |
| // Copyright (C) 2016-2023 Free Software Foundation, Inc. |
| // |
| // This file is part of the GNU ISO C++ Library. This library is free |
| // software; you can redistribute it and/or modify it under the |
| // terms of the GNU General Public License as published by the |
| // Free Software Foundation; either version 3, or (at your option) |
| // any later version. |
| |
| // This library is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| // GNU General Public License for more details. |
| |
| // You should have received a copy of the GNU General Public License along |
| // with this library; see the file COPYING3. If not see |
| // <http://www.gnu.org/licenses/>. |
| |
| #include <variant> |
| #include <string> |
| #include <vector> |
| |
| using namespace std; |
| |
| struct AllDeleted |
| { |
| AllDeleted() = delete; |
| AllDeleted(const AllDeleted&) = delete; |
| AllDeleted(AllDeleted&&) = delete; |
| AllDeleted& operator=(const AllDeleted&) = delete; |
| AllDeleted& operator=(AllDeleted&&) = delete; |
| }; |
| |
| struct Empty |
| { |
| Empty() { }; |
| Empty(const Empty&) { }; |
| Empty(Empty&&) { }; |
| Empty& operator=(const Empty&) { return *this; }; |
| Empty& operator=(Empty&&) { return *this; }; |
| }; |
| |
| struct DefaultNoexcept |
| { |
| DefaultNoexcept() noexcept = default; |
| DefaultNoexcept(const DefaultNoexcept&) noexcept = default; |
| DefaultNoexcept(DefaultNoexcept&&) noexcept = default; |
| DefaultNoexcept& operator=(const DefaultNoexcept&) noexcept = default; |
| DefaultNoexcept& operator=(DefaultNoexcept&&) noexcept = default; |
| }; |
| |
| struct MoveCtorOnly |
| { |
| MoveCtorOnly() noexcept = delete; |
| MoveCtorOnly(const MoveCtorOnly&) noexcept = delete; |
| MoveCtorOnly(MoveCtorOnly&&) noexcept { } |
| MoveCtorOnly& operator=(const MoveCtorOnly&) noexcept = delete; |
| MoveCtorOnly& operator=(MoveCtorOnly&&) noexcept = delete; |
| }; |
| |
| struct MoveCtorAndSwapOnly : MoveCtorOnly { }; |
| void swap(MoveCtorAndSwapOnly&, MoveCtorAndSwapOnly&) { } |
| |
| struct DeletedMoves |
| { |
| DeletedMoves() = default; |
| DeletedMoves(const DeletedMoves&) = default; |
| DeletedMoves(DeletedMoves&&) = delete; |
| DeletedMoves& operator=(const DeletedMoves&) = default; |
| DeletedMoves& operator=(DeletedMoves&&) = delete; |
| }; |
| |
| struct nonliteral |
| { |
| nonliteral() { } |
| |
| bool operator<(const nonliteral&) const; |
| bool operator<=(const nonliteral&) const; |
| bool operator==(const nonliteral&) const; |
| bool operator!=(const nonliteral&) const; |
| bool operator>=(const nonliteral&) const; |
| bool operator>(const nonliteral&) const; |
| }; |
| |
| struct virtual_default_dtor { |
| virtual ~virtual_default_dtor() = default; |
| }; |
| |
| void default_ctor() |
| { |
| static_assert(is_default_constructible_v<variant<int, string>>); |
| static_assert(is_default_constructible_v<variant<string, string>>); |
| static_assert(!is_default_constructible_v<variant<AllDeleted, string>>); |
| static_assert(is_default_constructible_v<variant<string, AllDeleted>>); |
| static_assert(is_default_constructible_v<variant<DeletedMoves>>); |
| |
| static_assert(noexcept(variant<int>())); |
| static_assert(!noexcept(variant<Empty>())); |
| static_assert(noexcept(variant<DefaultNoexcept>())); |
| { |
| variant<virtual_default_dtor> a; |
| } |
| } |
| |
| void copy_ctor() |
| { |
| static_assert(is_copy_constructible_v<variant<int, string>>); |
| static_assert(!is_copy_constructible_v<variant<AllDeleted, string>>); |
| static_assert(is_trivially_copy_constructible_v<variant<int>>); |
| static_assert(!is_trivially_copy_constructible_v<variant<std::string>>); |
| static_assert(is_trivially_copy_constructible_v<variant<DeletedMoves>>); |
| |
| { |
| variant<int> a; |
| static_assert(noexcept(variant<int>(a))); |
| } |
| { |
| variant<string> a; |
| static_assert(!noexcept(variant<string>(a))); |
| } |
| { |
| variant<int, string> a; |
| static_assert(!noexcept(variant<int, string>(a))); |
| } |
| { |
| variant<int, char> a; |
| static_assert(noexcept(variant<int, char>(a))); |
| } |
| } |
| |
| void move_ctor() |
| { |
| static_assert(is_move_constructible_v<variant<int, string>>); |
| static_assert(!is_move_constructible_v<variant<AllDeleted, string>>); |
| static_assert(is_move_constructible_v<variant<int, DeletedMoves>>); // uses copy ctor |
| static_assert(is_trivially_move_constructible_v<variant<int>>); |
| static_assert(!is_trivially_move_constructible_v<variant<std::string>>); |
| static_assert(!noexcept(variant<int, Empty>(declval<variant<int, Empty>>()))); |
| static_assert(noexcept(variant<int, DefaultNoexcept>(declval<variant<int, DefaultNoexcept>>()))); |
| } |
| |
| void arbitrary_ctor() |
| { |
| static_assert(!is_constructible_v<variant<string, string>, const char*>); |
| static_assert(is_constructible_v<variant<int, string>, const char*>); |
| static_assert(noexcept(variant<int, Empty>(int{}))); |
| static_assert(noexcept(variant<int, DefaultNoexcept>(int{}))); |
| static_assert(!noexcept(variant<int, Empty>(Empty{}))); |
| static_assert(noexcept(variant<int, DefaultNoexcept>(DefaultNoexcept{}))); |
| |
| // P0608R3 disallow narrowing conversions and boolean conversions |
| static_assert(!is_constructible_v<variant<float>, int>); |
| static_assert(!is_constructible_v<variant<float, vector<int>>, int>); |
| static_assert(is_constructible_v<variant<float, int>, char>); |
| static_assert(!is_constructible_v<variant<float, char>, int>); |
| static_assert(is_constructible_v<variant<float, long>, int>); |
| struct big_int { big_int(int) { } }; |
| static_assert(is_constructible_v<variant<float, big_int>, int>); |
| |
| static_assert(!is_constructible_v<variant<int>, unsigned>); |
| static_assert(!is_constructible_v<variant<bool>, int>); |
| static_assert(!is_constructible_v<variant<bool>, void*>); |
| |
| // P1957R2 Converting from T* to bool should be considered narrowing |
| struct ConvertibleToBool |
| { |
| operator bool() const { return true; } |
| }; |
| static_assert(is_constructible_v<variant<bool>, ConvertibleToBool>); |
| static_assert(is_constructible_v<variant<bool, int>, ConvertibleToBool>); |
| } |
| |
| struct None { None() = delete; }; |
| struct Any { template <typename T> Any(T&&) {} }; |
| |
| void in_place_index_ctor() |
| { |
| variant<string, string> a(in_place_index<0>, "a"); |
| variant<string, string> b(in_place_index<1>, {'a'}); |
| |
| static_assert(!is_constructible_v<variant<None, Any>, std::in_place_index_t<0>>, "PR libstdc++/90165"); |
| } |
| |
| void in_place_type_ctor() |
| { |
| variant<int, string, int> a(in_place_type<string>, "a"); |
| variant<int, string, int> b(in_place_type<string>, {'a'}); |
| static_assert(!is_constructible_v<variant<string, string>, in_place_type_t<string>, const char*>); |
| static_assert(!is_constructible_v<variant<None, Any>, std::in_place_type_t<None>>, "PR libstdc++/90165"); |
| } |
| |
| void dtor() |
| { |
| static_assert(is_destructible_v<variant<int, string>>); |
| static_assert(is_destructible_v<variant<AllDeleted, string>>); |
| } |
| |
| void copy_assign() |
| { |
| static_assert(is_copy_assignable_v<variant<int, string>>); |
| static_assert(!is_copy_assignable_v<variant<AllDeleted, string>>); |
| static_assert(is_trivially_copy_assignable_v<variant<int>>); |
| static_assert(!is_trivially_copy_assignable_v<variant<string>>); |
| static_assert(is_trivially_copy_assignable_v<variant<DeletedMoves>>); |
| { |
| variant<Empty> a; |
| static_assert(!noexcept(a = a)); |
| } |
| { |
| variant<DefaultNoexcept> a; |
| static_assert(noexcept(a = a)); |
| } |
| } |
| |
| void move_assign() |
| { |
| static_assert(is_move_assignable_v<variant<int, string>>); |
| static_assert(!is_move_assignable_v<variant<AllDeleted, string>>); |
| static_assert(is_move_assignable_v<variant<int, DeletedMoves>>); // uses copy assignment |
| static_assert(is_trivially_move_assignable_v<variant<int>>); |
| static_assert(!is_trivially_move_assignable_v<variant<string>>); |
| { |
| variant<Empty> a; |
| static_assert(!noexcept(a = std::move(a))); |
| } |
| { |
| variant<DefaultNoexcept> a; |
| static_assert(noexcept(a = std::move(a))); |
| } |
| } |
| |
| void arbitrary_assign() |
| { |
| static_assert(!is_assignable_v<variant<string, string>, const char*>); |
| static_assert(is_assignable_v<variant<int, string>, const char*>); |
| static_assert(noexcept(variant<int, Empty>() = int{})); |
| static_assert(noexcept(variant<int, DefaultNoexcept>() = int{})); |
| static_assert(!noexcept(variant<int, Empty>() = Empty{})); |
| static_assert(noexcept(variant<int, DefaultNoexcept>() = DefaultNoexcept{})); |
| } |
| |
| void test_get() |
| { |
| static_assert(is_same<decltype(get<0>(variant<int, string>())), int&&>::value); |
| static_assert(is_same<decltype(get<1>(variant<int, string>())), string&&>::value); |
| static_assert(is_same<decltype(get<1>(variant<int, const string>())), const string&&>::value); |
| |
| static_assert(is_same<decltype(get<int>(variant<int, string>())), int&&>::value); |
| static_assert(is_same<decltype(get<string>(variant<int, string>())), string&&>::value); |
| static_assert(is_same<decltype(get<const string>(variant<int, const string>())), const string&&>::value); |
| } |
| |
| void test_relational() |
| { |
| { |
| constexpr variant<int, nonliteral> a(42), b(43); |
| static_assert((a < b)); |
| static_assert(!(a > b)); |
| static_assert((a <= b)); |
| static_assert(!(a == b)); |
| static_assert((a != b)); |
| static_assert(!(a >= b)); |
| } |
| { |
| constexpr variant<int, nonliteral> a(42), b(42); |
| static_assert(!(a < b)); |
| static_assert(!(a > b)); |
| static_assert((a <= b)); |
| static_assert((a == b)); |
| static_assert(!(a != b)); |
| static_assert((a >= b)); |
| } |
| { |
| constexpr variant<int, nonliteral> a(43), b(42); |
| static_assert(!(a < b)); |
| static_assert((a > b)); |
| static_assert(!(a <= b)); |
| static_assert(!(a == b)); |
| static_assert((a != b)); |
| static_assert((a >= b)); |
| } |
| { |
| constexpr monostate a, b; |
| static_assert(!(a < b)); |
| static_assert(!(a > b)); |
| static_assert((a <= b)); |
| static_assert((a == b)); |
| static_assert(!(a != b)); |
| static_assert((a >= b)); |
| } |
| } |
| |
| // Not swappable, and variant<C> not swappable via the generic std::swap. |
| struct C { }; |
| void swap(C&, C&) = delete; |
| |
| static_assert( !std::is_swappable_v<variant<C>> ); |
| static_assert( !std::is_swappable_v<variant<int, C>> ); |
| static_assert( !std::is_swappable_v<variant<C, int>> ); |
| |
| // Not swappable, and variant<D> not swappable via the generic std::swap. |
| struct D { D(D&&) = delete; }; |
| |
| static_assert( !std::is_swappable_v<variant<D>> ); |
| static_assert( !std::is_swappable_v<variant<int, D>> ); |
| static_assert( !std::is_swappable_v<variant<D, int>> ); |
| |
| void test_swap() |
| { |
| static_assert(is_swappable_v<variant<int, string>>); |
| static_assert(!is_swappable_v<variant<MoveCtorOnly>>); |
| static_assert(is_swappable_v<variant<MoveCtorAndSwapOnly>>); |
| static_assert(!is_swappable_v<variant<AllDeleted>>); |
| } |
| |
| void test_visit() |
| { |
| { |
| struct Visitor |
| { |
| void operator()(monostate) {} |
| void operator()(const int&) {} |
| }; |
| struct CVisitor |
| { |
| void operator()(monostate) const {} |
| void operator()(const int&) const {} |
| }; |
| } |
| { |
| struct Visitor |
| { |
| bool operator()(int, float) { return false; } |
| bool operator()(int, double) { return false; } |
| bool operator()(char, float) { return false; } |
| bool operator()(char, double) { return false; } |
| }; |
| visit(Visitor(), variant<int, char>(), variant<float, double>()); |
| } |
| { |
| struct Visitor |
| { |
| constexpr bool operator()(const int&) { return true; } |
| constexpr bool operator()(const nonliteral&) { return false; } |
| }; |
| static_assert(visit(Visitor(), variant<int, nonliteral>(0))); |
| } |
| { |
| struct Visitor |
| { |
| constexpr bool operator()(const int&) { return true; } |
| constexpr bool operator()(const nonliteral&) { return false; } |
| }; |
| static_assert(visit(Visitor(), variant<int, nonliteral>(0))); |
| } |
| // PR libstdc++/79513 |
| { |
| std::variant<int> v [[gnu::unused]] (5); |
| std::visit([](int&){}, v); |
| std::visit([](int&&){}, std::move(v)); |
| } |
| } |
| |
| void test_constexpr() |
| { |
| constexpr variant<int> a; |
| static_assert(holds_alternative<int>(a)); |
| constexpr variant<int, char> b(in_place_index<0>, int{}); |
| static_assert(holds_alternative<int>(b)); |
| constexpr variant<int, char> c(in_place_type<int>, int{}); |
| static_assert(holds_alternative<int>(c)); |
| constexpr variant<int, char> d(in_place_index<1>, char{}); |
| static_assert(holds_alternative<char>(d)); |
| constexpr variant<int, char> e(in_place_type<char>, char{}); |
| static_assert(holds_alternative<char>(e)); |
| constexpr variant<int, char> f(char{}); |
| static_assert(holds_alternative<char>(f)); |
| |
| { |
| struct literal { |
| constexpr literal() = default; |
| }; |
| |
| constexpr variant<literal, nonliteral> v{}; |
| constexpr variant<literal, nonliteral> v1{in_place_type<literal>}; |
| constexpr variant<literal, nonliteral> v2{in_place_index<0>}; |
| } |
| |
| { |
| constexpr variant<int> a(42); |
| static_assert(get<0>(a) == 42); |
| } |
| { |
| constexpr variant<int, nonliteral> a(42); |
| static_assert(get<0>(a) == 42); |
| } |
| { |
| constexpr variant<nonliteral, int> a(42); |
| static_assert(get<1>(a) == 42); |
| } |
| { |
| constexpr variant<int> a(42); |
| static_assert(get<int>(a) == 42); |
| } |
| { |
| constexpr variant<int, nonliteral> a(42); |
| static_assert(get<int>(a) == 42); |
| } |
| { |
| constexpr variant<nonliteral, int> a(42); |
| static_assert(get<int>(a) == 42); |
| } |
| { |
| constexpr variant<int> a(42); |
| static_assert(get<0>(std::move(a)) == 42); |
| } |
| { |
| constexpr variant<int, nonliteral> a(42); |
| static_assert(get<0>(std::move(a)) == 42); |
| } |
| { |
| constexpr variant<nonliteral, int> a(42); |
| static_assert(get<1>(std::move(a)) == 42); |
| } |
| { |
| constexpr variant<int> a(42); |
| static_assert(get<int>(std::move(a)) == 42); |
| } |
| { |
| constexpr variant<int, nonliteral> a(42); |
| static_assert(get<int>(std::move(a)) == 42); |
| } |
| { |
| constexpr variant<nonliteral, int> a(42); |
| static_assert(get<int>(std::move(a)) == 42); |
| } |
| } |
| |
| void test_pr77641() |
| { |
| struct X { |
| constexpr X() { } |
| }; |
| |
| constexpr std::variant<X> v1 = X{}; |
| } |
| |
| namespace adl_trap |
| { |
| struct X { |
| X() = default; |
| X(int) { } |
| X(std::initializer_list<int>, const X&) { } |
| }; |
| template<typename T> void move(T&) { } |
| template<typename T> void forward(T&) { } |
| |
| struct Visitor { |
| template<typename T> void operator()(T&&) { } |
| }; |
| } |
| |
| void test_adl() |
| { |
| using adl_trap::X; |
| X x; |
| std::initializer_list<int> il; |
| adl_trap::Visitor vis; |
| |
| std::variant<X> v0(x); |
| v0 = x; |
| v0.emplace<0>(x); |
| v0.emplace<0>(il, x); |
| visit(vis, v0); |
| variant<X> v1{in_place_index<0>, x}; |
| variant<X> v2{in_place_type<X>, x}; |
| variant<X> v3{in_place_index<0>, il, x}; |
| variant<X> v4{in_place_type<X>, il, x}; |
| } |
| |
| void test_variant_alternative() |
| { |
| static_assert(is_same_v<variant_alternative_t<0, variant<int, string>>, int>); |
| static_assert(is_same_v<variant_alternative_t<1, variant<int, string>>, string>); |
| |
| static_assert(is_same_v<variant_alternative_t<0, const variant<int>>, const int>); |
| static_assert(is_same_v<variant_alternative_t<0, volatile variant<int>>, volatile int>); |
| static_assert(is_same_v<variant_alternative_t<0, const volatile variant<int>>, const volatile int>); |
| } |
| |
| template<typename V, typename T> |
| constexpr auto has_type_emplace(int) -> decltype((declval<V>().template emplace<T>(), true)) |
| { return true; }; |
| |
| template<typename V, typename T> |
| constexpr bool has_type_emplace(...) |
| { return false; }; |
| |
| template<typename V, size_t N> |
| constexpr auto has_index_emplace(int) -> decltype((declval<V>().template emplace<N>(), true)) |
| { return true; }; |
| |
| template<typename V, size_t T> |
| constexpr bool has_index_emplace(...) |
| { return false; }; |
| |
| void test_emplace() |
| { |
| static_assert(has_type_emplace<variant<int>, int>(0)); |
| static_assert(!has_type_emplace<variant<long>, int>(0)); |
| static_assert(has_index_emplace<variant<int>, 0>(0)); |
| static_assert(!has_type_emplace<variant<AllDeleted>, AllDeleted>(0)); |
| static_assert(!has_index_emplace<variant<AllDeleted>, 0>(0)); |
| static_assert(has_type_emplace<variant<int, AllDeleted>, int>(0)); |
| static_assert(has_index_emplace<variant<int, AllDeleted>, 0>(0)); |
| static_assert(has_type_emplace<variant<int, vector<int>, AllDeleted>, vector<int>>(0)); |
| static_assert(has_index_emplace<variant<int, vector<int>, AllDeleted>, 1>(0)); |
| |
| // The above tests only check the emplace members are available for |
| // overload resolution. The following odr-uses will instantiate them: |
| variant<int, vector<int>, AllDeleted> v; |
| v.emplace<0>(1); |
| v.emplace<int>(1); |
| v.emplace<1>(1, 1); |
| v.emplace<vector<int>>(1, 1); |
| v.emplace<1>({1, 2, 3, 4}); |
| v.emplace<vector<int>>({1, 2, 3, 4}); |
| } |
| |
| void test_triviality() |
| { |
| #define TEST_TEMPLATE(DT, CC, MC, CA, MA, CC_VAL, MC_VAL, CA_VAL, MA_VAL) \ |
| { \ |
| struct A \ |
| { \ |
| ~A() DT; \ |
| A(const A&) CC; \ |
| A(A&&) MC; \ |
| A& operator=(const A&) CA; \ |
| A& operator=(A&&) MA; \ |
| }; \ |
| static_assert(CC_VAL == is_trivially_copy_constructible_v<variant<A>>); \ |
| static_assert(MC_VAL == is_trivially_move_constructible_v<variant<A>>); \ |
| static_assert(CA_VAL == is_trivially_copy_assignable_v<variant<A>>); \ |
| static_assert(MA_VAL == is_trivially_move_assignable_v<variant<A>>); \ |
| } |
| TEST_TEMPLATE(=default, =default, =default, =default, =default, true, true, true, true) |
| TEST_TEMPLATE(=default, =default, =default, =default, , true, true, true, false) |
| TEST_TEMPLATE(=default, =default, =default, , =default, true, true, false, true) |
| TEST_TEMPLATE(=default, =default, =default, , , true, true, false, false) |
| TEST_TEMPLATE(=default, =default, , =default, =default, true, false, true, false) |
| TEST_TEMPLATE(=default, =default, , =default, , true, false, true, false) |
| TEST_TEMPLATE(=default, =default, , , =default, true, false, false, false) |
| TEST_TEMPLATE(=default, =default, , , , true, false, false, false) |
| TEST_TEMPLATE(=default, , =default, =default, =default, false, true, false, true) |
| TEST_TEMPLATE(=default, , =default, =default, , false, true, false, false) |
| TEST_TEMPLATE(=default, , =default, , =default, false, true, false, true) |
| TEST_TEMPLATE(=default, , =default, , , false, true, false, false) |
| TEST_TEMPLATE(=default, , , =default, =default, false, false, false, false) |
| TEST_TEMPLATE(=default, , , =default, , false, false, false, false) |
| TEST_TEMPLATE(=default, , , , =default, false, false, false, false) |
| TEST_TEMPLATE(=default, , , , , false, false, false, false) |
| TEST_TEMPLATE( , =default, =default, =default, =default, false, false, false, false) |
| TEST_TEMPLATE( , =default, =default, =default, , false, false, false, false) |
| TEST_TEMPLATE( , =default, =default, , =default, false, false, false, false) |
| TEST_TEMPLATE( , =default, =default, , , false, false, false, false) |
| TEST_TEMPLATE( , =default, , =default, =default, false, false, false, false) |
| TEST_TEMPLATE( , =default, , =default, , false, false, false, false) |
| TEST_TEMPLATE( , =default, , , =default, false, false, false, false) |
| TEST_TEMPLATE( , =default, , , , false, false, false, false) |
| TEST_TEMPLATE( , , =default, =default, =default, false, false, false, false) |
| TEST_TEMPLATE( , , =default, =default, , false, false, false, false) |
| TEST_TEMPLATE( , , =default, , =default, false, false, false, false) |
| TEST_TEMPLATE( , , =default, , , false, false, false, false) |
| TEST_TEMPLATE( , , , =default, =default, false, false, false, false) |
| TEST_TEMPLATE( , , , =default, , false, false, false, false) |
| TEST_TEMPLATE( , , , , =default, false, false, false, false) |
| TEST_TEMPLATE( , , , , , false, false, false, false) |
| #undef TEST_TEMPLATE |
| |
| #define TEST_TEMPLATE(CC, MC, CA, MA) \ |
| { \ |
| struct A \ |
| { \ |
| A(const A&) CC; \ |
| A(A&&) MC; \ |
| A& operator=(const A&) CA; \ |
| A& operator=(A&&) MA; \ |
| }; \ |
| static_assert(!is_trivially_copy_constructible_v<variant<AllDeleted, A>>); \ |
| static_assert(!is_trivially_move_constructible_v<variant<AllDeleted, A>>); \ |
| static_assert(!is_trivially_copy_assignable_v<variant<AllDeleted, A>>); \ |
| static_assert(!is_trivially_move_assignable_v<variant<AllDeleted, A>>); \ |
| } |
| TEST_TEMPLATE(=default, =default, =default, =default) |
| TEST_TEMPLATE(=default, =default, =default, ) |
| TEST_TEMPLATE(=default, =default, , =default) |
| TEST_TEMPLATE(=default, =default, , ) |
| TEST_TEMPLATE(=default, , =default, =default) |
| TEST_TEMPLATE(=default, , =default, ) |
| TEST_TEMPLATE(=default, , , =default) |
| TEST_TEMPLATE(=default, , , ) |
| TEST_TEMPLATE( , =default, =default, =default) |
| TEST_TEMPLATE( , =default, =default, ) |
| TEST_TEMPLATE( , =default, , =default) |
| TEST_TEMPLATE( , =default, , ) |
| TEST_TEMPLATE( , , =default, =default) |
| TEST_TEMPLATE( , , =default, ) |
| TEST_TEMPLATE( , , , =default) |
| TEST_TEMPLATE( , , , ) |
| #undef TEST_TEMPLATE |
| |
| static_assert(is_trivially_copy_constructible_v<variant<DefaultNoexcept, int, char, float, double>>); |
| static_assert(is_trivially_move_constructible_v<variant<DefaultNoexcept, int, char, float, double>>); |
| static_assert(is_trivially_copy_assignable_v<variant<DefaultNoexcept, int, char, float, double>>); |
| static_assert(is_trivially_move_assignable_v<variant<DefaultNoexcept, int, char, float, double>>); |
| } |