// { dg-options "-std=gnu++17" } // { dg-do compile } // Copyright (C) 2016 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 // . #include #include #include 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; }; void default_ctor() { static_assert(is_default_constructible_v>, ""); static_assert(is_default_constructible_v>, ""); static_assert(!is_default_constructible_v>, ""); static_assert(!is_default_constructible_v>, ""); static_assert(is_default_constructible_v>, ""); static_assert(noexcept(variant()), ""); static_assert(!noexcept(variant()), ""); static_assert(noexcept(variant()), ""); } void copy_ctor() { static_assert(is_copy_constructible_v>, ""); static_assert(!is_copy_constructible_v>, ""); { variant a; static_assert(!noexcept(variant(a)), ""); } { variant a; static_assert(!noexcept(variant(a)), ""); } { variant a; static_assert(!noexcept(variant(a)), ""); } { variant a; static_assert(!noexcept(variant(a)), ""); } } void move_ctor() { static_assert(is_move_constructible_v>, ""); static_assert(!is_move_constructible_v>, ""); static_assert(!noexcept(variant(declval>())), ""); static_assert(noexcept(variant(declval>())), ""); } void arbitrary_ctor() { static_assert(!is_constructible_v, const char*>, ""); static_assert(is_constructible_v, const char*>, ""); static_assert(noexcept(variant(int{})), ""); static_assert(noexcept(variant(int{})), ""); static_assert(!noexcept(variant(Empty{})), ""); static_assert(noexcept(variant(DefaultNoexcept{})), ""); } void in_place_index_ctor() { variant a(in_place<0>, "a"); variant b(in_place<1>, {'a'}); } void in_place_type_ctor() { variant a(in_place, "a"); variant b(in_place, {'a'}); static_assert(!is_constructible_v, in_place_type_t, const char*>, ""); } void uses_alloc_ctors() { std::allocator alloc; variant a(allocator_arg, alloc); static_assert(!is_constructible_v, allocator_arg_t, std::allocator>, ""); { variant b(allocator_arg, alloc, a); static_assert(!is_constructible_v, allocator_arg_t, std::allocator, const variant&>, ""); } { variant b(allocator_arg, alloc, std::move(a)); static_assert(!is_constructible_v, allocator_arg_t, std::allocator, variant&&>, ""); } { variant b(allocator_arg, alloc, "a"); static_assert(!is_constructible_v, allocator_arg_t, std::allocator, const char*>, ""); } { variant b(allocator_arg, alloc, in_place<0>, "a"); variant c(allocator_arg, alloc, in_place<1>, "a"); } { variant b(allocator_arg, alloc, in_place<0>, {'a'}); variant c(allocator_arg, alloc, in_place<1>, {'a'}); } { variant b(allocator_arg, alloc, in_place, "a"); } { variant b(allocator_arg, alloc, in_place, {'a'}); } } void dtor() { static_assert(is_destructible_v>, ""); static_assert(is_destructible_v>, ""); } void copy_assign() { static_assert(is_copy_assignable_v>, ""); static_assert(!is_copy_assignable_v>, ""); { variant a; static_assert(!noexcept(a = a), ""); } { variant a; static_assert(!noexcept(a = a), ""); } { float f1 = 1.0f, f2 = 2.0f; std::variant v1(f1); v1 = f2; } } void move_assign() { static_assert(is_move_assignable_v>, ""); static_assert(!is_move_assignable_v>, ""); { variant a; static_assert(!noexcept(a = std::move(a)), ""); } { variant a; static_assert(noexcept(a = std::move(a)), ""); } } void arbitrary_assign() { static_assert(!is_assignable_v, const char*>, ""); static_assert(is_assignable_v, const char*>, ""); static_assert(noexcept(variant() = int{}), ""); static_assert(noexcept(variant() = int{}), ""); static_assert(!noexcept(variant() = Empty{}), ""); static_assert(noexcept(variant() = DefaultNoexcept{}), ""); } void test_get() { { static_assert(is_same(variant())), int&&>::value, ""); static_assert(is_same(variant())), string&&>::value, ""); static_assert(is_same(variant())), string&>::value, ""); static_assert(is_same(variant())), string&&>::value, ""); static_assert(is_same(variant())), const string&&>::value, ""); static_assert(is_same(variant())), const string&>::value, ""); static_assert(is_same(variant())), const string&&>::value, ""); static_assert(is_same(variant())), int&&>::value, ""); static_assert(is_same(variant())), string&&>::value, ""); static_assert(is_same(variant())), string&>::value, ""); static_assert(is_same(variant())), string&&>::value, ""); static_assert(is_same(variant())), const string&&>::value, ""); static_assert(is_same(variant())), const string&>::value, ""); static_assert(is_same(variant())), const string&&>::value, ""); } { variant a; variant b; variant c; variant d; variant e; variant f; static_assert(is_same(a)), int&>::value, ""); static_assert(is_same(a)), string&>::value, ""); static_assert(is_same(b)), string&>::value, ""); static_assert(is_same(c)), string&>::value, ""); static_assert(is_same(e)), const string&>::value, ""); static_assert(is_same(e)), const string&>::value, ""); static_assert(is_same(f)), const string&>::value, ""); static_assert(is_same(a)), int&>::value, ""); static_assert(is_same(a)), string&>::value, ""); static_assert(is_same(b)), string&>::value, ""); static_assert(is_same(c)), string&>::value, ""); static_assert(is_same(e)), const string&>::value, ""); static_assert(is_same(e)), const string&>::value, ""); static_assert(is_same(f)), const string&>::value, ""); static_assert(is_same(&a)), int*>::value, ""); static_assert(is_same(&a)), string*>::value, ""); static_assert(is_same(&b)), string*>::value, ""); static_assert(is_same(&c)), string*>::value, ""); static_assert(is_same(&e)), const string*>::value, ""); static_assert(is_same(&e)), const string*>::value, ""); static_assert(is_same(&f)), const string*>::value, ""); static_assert(is_same(&a)), int*>::value, ""); static_assert(is_same(&a)), string*>::value, ""); static_assert(is_same(&b)), string*>::value, ""); static_assert(is_same(&c)), string*>::value, ""); static_assert(is_same(&e)), const string*>::value, ""); static_assert(is_same(&e)), const string*>::value, ""); static_assert(is_same(&f)), const string*>::value, ""); } { const variant a; const variant b; const variant c; const variant d; const variant e; const variant f; static_assert(is_same(a)), const int&>::value, ""); static_assert(is_same(a)), const string&>::value, ""); static_assert(is_same(b)), string&>::value, ""); static_assert(is_same(c)), string&>::value, ""); static_assert(is_same(d)), const string&>::value, ""); static_assert(is_same(e)), const string&>::value, ""); static_assert(is_same(f)), const string&>::value, ""); static_assert(is_same(a)), const int&>::value, ""); static_assert(is_same(a)), const string&>::value, ""); static_assert(is_same(b)), string&>::value, ""); static_assert(is_same(c)), string&>::value, ""); static_assert(is_same(d)), const string&>::value, ""); static_assert(is_same(e)), const string&>::value, ""); static_assert(is_same(f)), const string&>::value, ""); static_assert(is_same(&a)), const int*>::value, ""); static_assert(is_same(&a)), const string*>::value, ""); static_assert(is_same(&b)), string*>::value, ""); static_assert(is_same(&c)), string*>::value, ""); static_assert(is_same(&d)), const string*>::value, ""); static_assert(is_same(&e)), const string*>::value, ""); static_assert(is_same(&f)), const string*>::value, ""); static_assert(is_same(&a)), const int*>::value, ""); static_assert(is_same(&a)), const string*>::value, ""); static_assert(is_same(&b)), string*>::value, ""); static_assert(is_same(&c)), string*>::value, ""); static_assert(is_same(&d)), const string*>::value, ""); static_assert(is_same(&e)), const string*>::value, ""); static_assert(is_same(&f)), const string*>::value, ""); } } void test_relational() { { const variant a, b; (void)(a < b); (void)(a > b); (void)(a <= b); (void)(a == b); (void)(a != b); (void)(a >= b); } { const monostate a, b; (void)(a < b); (void)(a > b); (void)(a <= b); (void)(a == b); (void)(a != b); (void)(a >= b); } } void test_swap() { variant a, b; a.swap(b); swap(a, b); } void test_visit() { { struct Visitor { void operator()(monostate) {} void operator()(const int&) {} }; struct CVisitor { void operator()(monostate) const {} void operator()(const int&) const {} }; variant a; const variant b; Visitor v; const CVisitor u; static_assert(is_same::value, ""); static_assert(is_same::value, ""); static_assert(is_same::value, ""); static_assert(is_same::value, ""); static_assert(is_same::value, ""); static_assert(is_same::value, ""); } { 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(), variant()); } } void test_constexpr() { constexpr variant a; static_assert(holds_alternative(a), ""); constexpr variant b(in_place<0>, int{}); static_assert(holds_alternative(b), ""); constexpr variant c(in_place, int{}); static_assert(holds_alternative(c), ""); constexpr variant d(in_place<1>, char{}); static_assert(holds_alternative(d), ""); constexpr variant e(in_place, char{}); static_assert(holds_alternative(e), ""); constexpr variant f(char{}); static_assert(holds_alternative(f), ""); { struct literal { constexpr literal() = default; }; struct nonliteral { nonliteral() { } }; constexpr variant v{}; constexpr variant v1{in_place}; constexpr variant v2{in_place<0>}; } } void test_void() { static_assert(is_same(variant()))>::value, ""); static_assert(!is_default_constructible_v>, ""); static_assert(!is_copy_constructible_v>, ""); static_assert(!is_move_constructible_v>, ""); static_assert(!is_copy_assignable_v>, ""); static_assert(!is_move_assignable_v>, ""); variant v; v = 3; v = "asdf"; } void test_pr77641() { struct X { constexpr X() { } }; constexpr std::variant v1 = X{}; } namespace adl_trap { struct X { X() = default; X(int) { } X(std::initializer_list, const X&) { } }; template void move(T&) { } template void forward(T&) { } struct Visitor { template void operator()(T&&) { } }; } void test_adl() { using adl_trap::X; using std::allocator_arg; X x; std::allocator a; std::initializer_list il; adl_trap::Visitor vis; std::variant v0(x); v0 = x; v0.emplace<0>(x); v0.emplace<0>(il, x); visit(vis, v0); variant v1{in_place<0>, x}; variant v2{in_place, x}; variant v3{in_place<0>, il, x}; variant v4{in_place, il, x}; variant v5{allocator_arg, a, in_place<0>, x}; variant v6{allocator_arg, a, in_place, x}; variant v7{allocator_arg, a, in_place<0>, il, x}; variant v8{allocator_arg, a, in_place, il, x}; variant v9{allocator_arg, a, in_place, 1}; std::variant vr0(x); vr0 = x; variant vr1{in_place<0>, x}; variant vr2{in_place, x}; variant vr3{allocator_arg, a, in_place<0>, x}; variant vr4{allocator_arg, a, in_place, x}; }