// { 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};
}