Implement C++17 <variant>. Patch from Michael Park!
This patch was reviewed as https://reviews.llvm.org/D23263. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@288547 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
1553
include/variant
Normal file
1553
include/variant
Normal file
File diff suppressed because it is too large
Load Diff
18
src/variant.cpp
Normal file
18
src/variant.cpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//===------------------------ variant.cpp ---------------------------------===//
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "variant"
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
|
||||||
|
const char* bad_variant_access::what() const noexcept {
|
||||||
|
return "bad_variant_access";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace std
|
||||||
@@ -0,0 +1,181 @@
|
|||||||
|
// -*- 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& 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
test_copy_assignment_same_index();
|
||||||
|
test_copy_assignment_different_index();
|
||||||
|
test_copy_assignment_sfinae();
|
||||||
|
}
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
// -*- 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& 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
test_move_assignment_same_index();
|
||||||
|
test_move_assignment_different_index();
|
||||||
|
test_move_assignment_sfinae();
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
@@ -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();
|
||||||
|
}
|
||||||
20
test/libcxx/utilities/variant/version.pass.cpp
Normal file
20
test/libcxx/utilities/variant/version.pass.cpp
Normal file
@@ -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()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
|
|
||||||
# FIXME: Libc++ does not yet implement variant but other STLs benefit from
|
|
||||||
# having our tests in-tree. This must be removed when <variant> is added.
|
|
||||||
if 'libc++' in config.available_features:
|
|
||||||
config.unsupported = True
|
|
||||||
@@ -32,17 +32,17 @@ void test_const_get_if() {
|
|||||||
static_assert(std::get_if<0>(v) == nullptr, "");
|
static_assert(std::get_if<0>(v) == nullptr, "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long>;
|
using V = std::variant<int, const long>;
|
||||||
constexpr V v(42);
|
constexpr V v(42);
|
||||||
ASSERT_NOEXCEPT(std::get_if<0>(&v));
|
ASSERT_NOEXCEPT(std::get_if<0>(&v));
|
||||||
ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), int const *);
|
ASSERT_SAME_TYPE(decltype(std::get_if<0>(&v)), const int *);
|
||||||
static_assert(*std::get_if<0>(&v) == 42, "");
|
static_assert(*std::get_if<0>(&v) == 42, "");
|
||||||
static_assert(std::get_if<1>(&v) == nullptr, "");
|
static_assert(std::get_if<1>(&v) == nullptr, "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long>;
|
using V = std::variant<int, const long>;
|
||||||
constexpr V v(42l);
|
constexpr V v(42l);
|
||||||
ASSERT_SAME_TYPE(decltype(std::get_if<1>(&v)), long const *);
|
ASSERT_SAME_TYPE(decltype(std::get_if<1>(&v)), const long *);
|
||||||
static_assert(*std::get_if<1>(&v) == 42, "");
|
static_assert(*std::get_if<1>(&v) == 42, "");
|
||||||
static_assert(std::get_if<0>(&v) == nullptr, "");
|
static_assert(std::get_if<0>(&v) == nullptr, "");
|
||||||
}
|
}
|
||||||
@@ -87,9 +87,9 @@ void test_get_if() {
|
|||||||
assert(std::get_if<1>(&v) == nullptr);
|
assert(std::get_if<1>(&v) == nullptr);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long>;
|
using V = std::variant<int, const long>;
|
||||||
V v(42l);
|
V v(42l);
|
||||||
ASSERT_SAME_TYPE(decltype(std::get_if<1>(&v)), long *);
|
ASSERT_SAME_TYPE(decltype(std::get_if<1>(&v)), const long *);
|
||||||
assert(*std::get_if<1>(&v) == 42);
|
assert(*std::get_if<1>(&v) == 42);
|
||||||
assert(std::get_if<0>(&v) == nullptr);
|
assert(std::get_if<0>(&v) == nullptr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,18 +30,18 @@ void test_const_get_if() {
|
|||||||
static_assert(std::get_if<int>(v) == nullptr, "");
|
static_assert(std::get_if<int>(v) == nullptr, "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long>;
|
using V = std::variant<int, const long>;
|
||||||
constexpr V v(42);
|
constexpr V v(42);
|
||||||
ASSERT_NOEXCEPT(std::get_if<int>(&v));
|
ASSERT_NOEXCEPT(std::get_if<int>(&v));
|
||||||
ASSERT_SAME_TYPE(decltype(std::get_if<int>(&v)), int const *);
|
ASSERT_SAME_TYPE(decltype(std::get_if<int>(&v)), const int *);
|
||||||
static_assert(*std::get_if<int>(&v) == 42, "");
|
static_assert(*std::get_if<int>(&v) == 42, "");
|
||||||
static_assert(std::get_if<long>(&v) == nullptr, "");
|
static_assert(std::get_if<const long>(&v) == nullptr, "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long>;
|
using V = std::variant<int, const long>;
|
||||||
constexpr V v(42l);
|
constexpr V v(42l);
|
||||||
ASSERT_SAME_TYPE(decltype(std::get_if<long>(&v)), long const *);
|
ASSERT_SAME_TYPE(decltype(std::get_if<const long>(&v)), const long *);
|
||||||
static_assert(*std::get_if<long>(&v) == 42, "");
|
static_assert(*std::get_if<const long>(&v) == 42, "");
|
||||||
static_assert(std::get_if<int>(&v) == nullptr, "");
|
static_assert(std::get_if<int>(&v) == nullptr, "");
|
||||||
}
|
}
|
||||||
// FIXME: Remove these once reference support is reinstated
|
// FIXME: Remove these once reference support is reinstated
|
||||||
@@ -77,18 +77,18 @@ void test_get_if() {
|
|||||||
assert(std::get_if<int>(v) == nullptr);
|
assert(std::get_if<int>(v) == nullptr);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long>;
|
using V = std::variant<int, const long>;
|
||||||
V v(42);
|
V v(42);
|
||||||
ASSERT_NOEXCEPT(std::get_if<int>(&v));
|
ASSERT_NOEXCEPT(std::get_if<int>(&v));
|
||||||
ASSERT_SAME_TYPE(decltype(std::get_if<int>(&v)), int *);
|
ASSERT_SAME_TYPE(decltype(std::get_if<int>(&v)), int *);
|
||||||
assert(*std::get_if<int>(&v) == 42);
|
assert(*std::get_if<int>(&v) == 42);
|
||||||
assert(std::get_if<long>(&v) == nullptr);
|
assert(std::get_if<const long>(&v) == nullptr);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long>;
|
using V = std::variant<int, const long>;
|
||||||
V v(42l);
|
V v(42l);
|
||||||
ASSERT_SAME_TYPE(decltype(std::get_if<long>(&v)), long *);
|
ASSERT_SAME_TYPE(decltype(std::get_if<const long>(&v)), const long *);
|
||||||
assert(*std::get_if<long>(&v) == 42);
|
assert(*std::get_if<const long>(&v) == 42);
|
||||||
assert(std::get_if<int>(&v) == nullptr);
|
assert(std::get_if<int>(&v) == nullptr);
|
||||||
}
|
}
|
||||||
// FIXME: Remove these once reference support is reinstated
|
// FIXME: Remove these once reference support is reinstated
|
||||||
|
|||||||
@@ -34,16 +34,16 @@
|
|||||||
|
|
||||||
void test_const_lvalue_get() {
|
void test_const_lvalue_get() {
|
||||||
{
|
{
|
||||||
using V = std::variant<int>;
|
using V = std::variant<int, const long>;
|
||||||
constexpr V v(42);
|
constexpr V v(42);
|
||||||
// ASSERT_NOT_NOEXCEPT(std::get<0>(v));
|
ASSERT_NOT_NOEXCEPT(std::get<0>(v));
|
||||||
ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int const &);
|
ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
|
||||||
static_assert(std::get<0>(v) == 42, "");
|
static_assert(std::get<0>(v) == 42, "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long>;
|
using V = std::variant<int, const long>;
|
||||||
constexpr V v(42l);
|
constexpr V v(42l);
|
||||||
ASSERT_SAME_TYPE(decltype(std::get<1>(v)), long const &);
|
ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &);
|
||||||
static_assert(std::get<1>(v) == 42, "");
|
static_assert(std::get<1>(v) == 42, "");
|
||||||
}
|
}
|
||||||
// FIXME: Remove these once reference support is reinstated
|
// FIXME: Remove these once reference support is reinstated
|
||||||
@@ -74,16 +74,16 @@ void test_const_lvalue_get() {
|
|||||||
|
|
||||||
void test_lvalue_get() {
|
void test_lvalue_get() {
|
||||||
{
|
{
|
||||||
using V = std::variant<int>;
|
using V = std::variant<int, const long>;
|
||||||
V v(42);
|
V v(42);
|
||||||
ASSERT_NOT_NOEXCEPT(std::get<0>(v));
|
ASSERT_NOT_NOEXCEPT(std::get<0>(v));
|
||||||
ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
|
ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int &);
|
||||||
assert(std::get<0>(v) == 42);
|
assert(std::get<0>(v) == 42);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long>;
|
using V = std::variant<int, const long>;
|
||||||
V v(42l);
|
V v(42l);
|
||||||
ASSERT_SAME_TYPE(decltype(std::get<1>(v)), long &);
|
ASSERT_SAME_TYPE(decltype(std::get<1>(v)), const long &);
|
||||||
assert(std::get<1>(v) == 42);
|
assert(std::get<1>(v) == 42);
|
||||||
}
|
}
|
||||||
// FIXME: Remove these once reference support is reinstated
|
// FIXME: Remove these once reference support is reinstated
|
||||||
@@ -121,16 +121,16 @@ void test_lvalue_get() {
|
|||||||
|
|
||||||
void test_rvalue_get() {
|
void test_rvalue_get() {
|
||||||
{
|
{
|
||||||
using V = std::variant<int>;
|
using V = std::variant<int, const long>;
|
||||||
V v(42);
|
V v(42);
|
||||||
ASSERT_NOT_NOEXCEPT(std::get<0>(std::move(v)));
|
ASSERT_NOT_NOEXCEPT(std::get<0>(std::move(v)));
|
||||||
ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&);
|
ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), int &&);
|
||||||
assert(std::get<0>(std::move(v)) == 42);
|
assert(std::get<0>(std::move(v)) == 42);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long>;
|
using V = std::variant<int, const long>;
|
||||||
V v(42l);
|
V v(42l);
|
||||||
ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), long &&);
|
ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), const long &&);
|
||||||
assert(std::get<1>(std::move(v)) == 42);
|
assert(std::get<1>(std::move(v)) == 42);
|
||||||
}
|
}
|
||||||
// FIXME: Remove these once reference support is reinstated
|
// FIXME: Remove these once reference support is reinstated
|
||||||
@@ -170,14 +170,14 @@ void test_rvalue_get() {
|
|||||||
|
|
||||||
void test_const_rvalue_get() {
|
void test_const_rvalue_get() {
|
||||||
{
|
{
|
||||||
using V = std::variant<int>;
|
using V = std::variant<int, const long>;
|
||||||
const V v(42);
|
const V v(42);
|
||||||
ASSERT_NOT_NOEXCEPT(std::get<0>(std::move(v)));
|
ASSERT_NOT_NOEXCEPT(std::get<0>(std::move(v)));
|
||||||
ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&);
|
ASSERT_SAME_TYPE(decltype(std::get<0>(std::move(v))), const int &&);
|
||||||
assert(std::get<0>(std::move(v)) == 42);
|
assert(std::get<0>(std::move(v)) == 42);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long>;
|
using V = std::variant<int, const long>;
|
||||||
const V v(42l);
|
const V v(42l);
|
||||||
ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), const long &&);
|
ASSERT_SAME_TYPE(decltype(std::get<1>(std::move(v))), const long &&);
|
||||||
assert(std::get<1>(std::move(v)) == 42);
|
assert(std::get<1>(std::move(v)) == 42);
|
||||||
@@ -234,7 +234,7 @@ void test_throws_for_all_value_categories() {
|
|||||||
using Idx = decltype(idx);
|
using Idx = decltype(idx);
|
||||||
try {
|
try {
|
||||||
std::get<Idx::value>(std::forward<decltype(v)>(v));
|
std::get<Idx::value>(std::forward<decltype(v)>(v));
|
||||||
} catch (std::bad_variant_access const &) {
|
} catch (const std::bad_variant_access &) {
|
||||||
return true;
|
return true;
|
||||||
} catch (...) { /* ... */
|
} catch (...) { /* ... */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,17 +28,17 @@
|
|||||||
|
|
||||||
void test_const_lvalue_get() {
|
void test_const_lvalue_get() {
|
||||||
{
|
{
|
||||||
using V = std::variant<int>;
|
using V = std::variant<int, const long>;
|
||||||
constexpr V v(42);
|
constexpr V v(42);
|
||||||
// ASSERT_NOT_NOEXCEPT(std::get<int>(v));
|
ASSERT_NOT_NOEXCEPT(std::get<int>(v));
|
||||||
ASSERT_SAME_TYPE(decltype(std::get<0>(v)), int const &);
|
ASSERT_SAME_TYPE(decltype(std::get<0>(v)), const int &);
|
||||||
static_assert(std::get<int>(v) == 42, "");
|
static_assert(std::get<int>(v) == 42, "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long>;
|
using V = std::variant<int, const long>;
|
||||||
constexpr V v(42l);
|
constexpr V v(42l);
|
||||||
ASSERT_SAME_TYPE(decltype(std::get<long>(v)), long const &);
|
ASSERT_SAME_TYPE(decltype(std::get<const long>(v)), const long &);
|
||||||
static_assert(std::get<long>(v) == 42, "");
|
static_assert(std::get<const long>(v) == 42, "");
|
||||||
}
|
}
|
||||||
// FIXME: Remove these once reference support is reinstated
|
// FIXME: Remove these once reference support is reinstated
|
||||||
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
||||||
@@ -68,17 +68,17 @@ void test_const_lvalue_get() {
|
|||||||
|
|
||||||
void test_lvalue_get() {
|
void test_lvalue_get() {
|
||||||
{
|
{
|
||||||
using V = std::variant<int>;
|
using V = std::variant<int, const long>;
|
||||||
V v(42);
|
V v(42);
|
||||||
ASSERT_NOT_NOEXCEPT(std::get<int>(v));
|
ASSERT_NOT_NOEXCEPT(std::get<int>(v));
|
||||||
ASSERT_SAME_TYPE(decltype(std::get<int>(v)), int &);
|
ASSERT_SAME_TYPE(decltype(std::get<int>(v)), int &);
|
||||||
assert(std::get<int>(v) == 42);
|
assert(std::get<int>(v) == 42);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long>;
|
using V = std::variant<int, const long>;
|
||||||
V v(42l);
|
V v(42l);
|
||||||
ASSERT_SAME_TYPE(decltype(std::get<long>(v)), long &);
|
ASSERT_SAME_TYPE(decltype(std::get<const long>(v)), const long &);
|
||||||
assert(std::get<long>(v) == 42);
|
assert(std::get<const long>(v) == 42);
|
||||||
}
|
}
|
||||||
// FIXME: Remove these once reference support is reinstated
|
// FIXME: Remove these once reference support is reinstated
|
||||||
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
||||||
@@ -115,17 +115,18 @@ void test_lvalue_get() {
|
|||||||
|
|
||||||
void test_rvalue_get() {
|
void test_rvalue_get() {
|
||||||
{
|
{
|
||||||
using V = std::variant<int>;
|
using V = std::variant<int, const long>;
|
||||||
V v(42);
|
V v(42);
|
||||||
ASSERT_NOT_NOEXCEPT(std::get<int>(std::move(v)));
|
ASSERT_NOT_NOEXCEPT(std::get<int>(std::move(v)));
|
||||||
ASSERT_SAME_TYPE(decltype(std::get<int>(std::move(v))), int &&);
|
ASSERT_SAME_TYPE(decltype(std::get<int>(std::move(v))), int &&);
|
||||||
assert(std::get<int>(std::move(v)) == 42);
|
assert(std::get<int>(std::move(v)) == 42);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long>;
|
using V = std::variant<int, const long>;
|
||||||
V v(42l);
|
V v(42l);
|
||||||
ASSERT_SAME_TYPE(decltype(std::get<long>(std::move(v))), long &&);
|
ASSERT_SAME_TYPE(decltype(std::get<const long>(std::move(v))),
|
||||||
assert(std::get<long>(std::move(v)) == 42);
|
const long &&);
|
||||||
|
assert(std::get<const long>(std::move(v)) == 42);
|
||||||
}
|
}
|
||||||
// FIXME: Remove these once reference support is reinstated
|
// FIXME: Remove these once reference support is reinstated
|
||||||
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
||||||
@@ -166,17 +167,18 @@ void test_rvalue_get() {
|
|||||||
|
|
||||||
void test_const_rvalue_get() {
|
void test_const_rvalue_get() {
|
||||||
{
|
{
|
||||||
using V = std::variant<int>;
|
using V = std::variant<int, const long>;
|
||||||
const V v(42);
|
const V v(42);
|
||||||
ASSERT_NOT_NOEXCEPT(std::get<int>(std::move(v)));
|
ASSERT_NOT_NOEXCEPT(std::get<int>(std::move(v)));
|
||||||
ASSERT_SAME_TYPE(decltype(std::get<int>(std::move(v))), const int &&);
|
ASSERT_SAME_TYPE(decltype(std::get<int>(std::move(v))), const int &&);
|
||||||
assert(std::get<int>(std::move(v)) == 42);
|
assert(std::get<int>(std::move(v)) == 42);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long>;
|
using V = std::variant<int, const long>;
|
||||||
const V v(42l);
|
const V v(42l);
|
||||||
ASSERT_SAME_TYPE(decltype(std::get<long>(std::move(v))), const long &&);
|
ASSERT_SAME_TYPE(decltype(std::get<const long>(std::move(v))),
|
||||||
assert(std::get<long>(std::move(v)) == 42);
|
const long &&);
|
||||||
|
assert(std::get<const long>(std::move(v)) == 42);
|
||||||
}
|
}
|
||||||
// FIXME: Remove these once reference support is reinstated
|
// FIXME: Remove these once reference support is reinstated
|
||||||
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
||||||
@@ -232,7 +234,7 @@ void test_throws_for_all_value_categories() {
|
|||||||
using Idx = decltype(idx);
|
using Idx = decltype(idx);
|
||||||
try {
|
try {
|
||||||
std::get<typename Idx::type>(std::forward<decltype(v)>(v));
|
std::get<typename Idx::type>(std::forward<decltype(v)>(v));
|
||||||
} catch (std::bad_variant_access const &) {
|
} catch (const std::bad_variant_access &) {
|
||||||
return true;
|
return true;
|
||||||
} catch (...) { /* ... */
|
} catch (...) { /* ... */
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
// template <class T, class... Types>
|
// template <class T, class... Types>
|
||||||
// constexpr bool holds_alternative(const variant<Types...>& v) noexcept;
|
// constexpr bool holds_alternative(const variant<Types...>& v) noexcept;
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
@@ -32,6 +33,6 @@ int main() {
|
|||||||
{ // noexcept test
|
{ // noexcept test
|
||||||
using V = std::variant<int>;
|
using V = std::variant<int>;
|
||||||
const V v;
|
const V v;
|
||||||
static_assert(noexcept(std::holds_alternative<int>(v)), "must be noexcept");
|
ASSERT_NOEXCEPT(std::holds_alternative<int>(v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||||
namespace std {
|
namespace std {
|
||||||
template <> struct hash<::MakeEmptyT> {
|
template <> struct hash<::MakeEmptyT> {
|
||||||
size_t operator()(::MakeEmptyT const &) const {
|
size_t operator()(const ::MakeEmptyT &) const {
|
||||||
assert(false);
|
assert(false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -40,7 +40,6 @@ void test_hash_variant() {
|
|||||||
const V v(std::in_place_index<0>, 42);
|
const V v(std::in_place_index<0>, 42);
|
||||||
const V v_copy = v;
|
const V v_copy = v;
|
||||||
V v2(std::in_place_index<0>, 100);
|
V v2(std::in_place_index<0>, 100);
|
||||||
const V v3(std::in_place_index<2>, 42);
|
|
||||||
const H h{};
|
const H h{};
|
||||||
assert(h(v) == h(v));
|
assert(h(v) == h(v));
|
||||||
assert(h(v) != h(v2));
|
assert(h(v) != h(v2));
|
||||||
|
|||||||
@@ -66,10 +66,10 @@ int main() {
|
|||||||
}
|
}
|
||||||
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
||||||
{
|
{
|
||||||
using V = std::variant<int, int &, int const &, int &&, long double>;
|
using V = std::variant<int, int &, const int &, int &&, long double>;
|
||||||
test<V, 0, int>();
|
test<V, 0, int>();
|
||||||
test<V, 1, int &>();
|
test<V, 1, int &>();
|
||||||
test<V, 2, int const &>();
|
test<V, 2, const int &>();
|
||||||
test<V, 3, int &&>();
|
test<V, 3, int &&>();
|
||||||
test<V, 4, long double>();
|
test<V, 4, long double>();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
// constexpr bool operator==(monostate, monostate) noexcept { return true; }
|
// constexpr bool operator==(monostate, monostate) noexcept { return true; }
|
||||||
// constexpr bool operator!=(monostate, monostate) noexcept { return false; }
|
// constexpr bool operator!=(monostate, monostate) noexcept { return false; }
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
@@ -29,26 +30,26 @@ int main() {
|
|||||||
constexpr M m2{};
|
constexpr M m2{};
|
||||||
{
|
{
|
||||||
static_assert((m1 < m2) == false, "");
|
static_assert((m1 < m2) == false, "");
|
||||||
static_assert(noexcept(m1 < m2), "");
|
ASSERT_NOEXCEPT(m1 < m2);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
static_assert((m1 > m2) == false, "");
|
static_assert((m1 > m2) == false, "");
|
||||||
static_assert(noexcept(m1 > m2), "");
|
ASSERT_NOEXCEPT(m1 > m2);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
static_assert((m1 <= m2) == true, "");
|
static_assert((m1 <= m2) == true, "");
|
||||||
static_assert(noexcept(m1 <= m2), "");
|
ASSERT_NOEXCEPT(m1 <= m2);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
static_assert((m1 >= m2) == true, "");
|
static_assert((m1 >= m2) == true, "");
|
||||||
static_assert(noexcept(m1 >= m2), "");
|
ASSERT_NOEXCEPT(m1 >= m2);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
static_assert((m1 == m2) == true, "");
|
static_assert((m1 == m2) == true, "");
|
||||||
static_assert(noexcept(m1 == m2), "");
|
ASSERT_NOEXCEPT(m1 == m2);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
static_assert((m1 != m2) == false, "");
|
static_assert((m1 != m2) == false, "");
|
||||||
static_assert(noexcept(m1 != m2), "");
|
ASSERT_NOEXCEPT(m1 != m2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,27 +49,27 @@ struct MakeEmptyT {
|
|||||||
MakeEmptyT(MakeEmptyT &&) { throw 42; }
|
MakeEmptyT(MakeEmptyT &&) { throw 42; }
|
||||||
MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
|
MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
|
||||||
};
|
};
|
||||||
inline bool operator==(MakeEmptyT const &, MakeEmptyT const &) {
|
inline bool operator==(const MakeEmptyT &, const MakeEmptyT &) {
|
||||||
assert(false);
|
assert(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
inline bool operator!=(MakeEmptyT const &, MakeEmptyT const &) {
|
inline bool operator!=(const MakeEmptyT &, const MakeEmptyT &) {
|
||||||
assert(false);
|
assert(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
inline bool operator<(MakeEmptyT const &, MakeEmptyT const &) {
|
inline bool operator<(const MakeEmptyT &, const MakeEmptyT &) {
|
||||||
assert(false);
|
assert(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
inline bool operator<=(MakeEmptyT const &, MakeEmptyT const &) {
|
inline bool operator<=(const MakeEmptyT &, const MakeEmptyT &) {
|
||||||
assert(false);
|
assert(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
inline bool operator>(MakeEmptyT const &, MakeEmptyT const &) {
|
inline bool operator>(const MakeEmptyT &, const MakeEmptyT &) {
|
||||||
assert(false);
|
assert(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
inline bool operator>=(MakeEmptyT const &, MakeEmptyT const &) {
|
inline bool operator>=(const MakeEmptyT &, const MakeEmptyT &) {
|
||||||
assert(false);
|
assert(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -158,7 +158,7 @@ void test_equality() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class Var>
|
template <class Var>
|
||||||
constexpr bool test_less(Var const &l, Var const &r, bool expect_less,
|
constexpr bool test_less(const Var &l, const Var &r, bool expect_less,
|
||||||
bool expect_greater) {
|
bool expect_greater) {
|
||||||
return ((l < r) == expect_less) && (!(l >= r) == expect_less) &&
|
return ((l < r) == expect_less) && (!(l >= r) == expect_less) &&
|
||||||
((l > r) == expect_greater) && (!(l <= r) == expect_greater);
|
((l > r) == expect_greater) && (!(l <= r) == expect_greater);
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ void test_T_assignment_sfinae() {
|
|||||||
static_assert(!std::is_assignable<V, int>::value, "ambiguous");
|
static_assert(!std::is_assignable<V, int>::value, "ambiguous");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, int const &>;
|
using V = std::variant<int, const int &>;
|
||||||
static_assert(!std::is_assignable<V, int>::value, "ambiguous");
|
static_assert(!std::is_assignable<V, int>::value, "ambiguous");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -149,9 +149,9 @@ void test_T_assignment_basic() {
|
|||||||
v = std::move(x);
|
v = std::move(x);
|
||||||
assert(v.index() == 1);
|
assert(v.index() == 1);
|
||||||
assert(&std::get<1>(v) == &x);
|
assert(&std::get<1>(v) == &x);
|
||||||
// 'long' is selected by FUN(int const&) since 'int const&' cannot bind
|
// 'long' is selected by FUN(const int &) since 'const int &' cannot bind
|
||||||
// to 'int&'.
|
// to 'int&'.
|
||||||
int const &cx = x;
|
const int &cx = x;
|
||||||
v = cx;
|
v = cx;
|
||||||
assert(v.index() == 2);
|
assert(v.index() == 2);
|
||||||
assert(std::get<2>(v) == 42);
|
assert(std::get<2>(v) == 42);
|
||||||
|
|||||||
@@ -24,32 +24,32 @@
|
|||||||
#include "test_macros.h"
|
#include "test_macros.h"
|
||||||
|
|
||||||
struct NoCopy {
|
struct NoCopy {
|
||||||
NoCopy(NoCopy const &) = delete;
|
NoCopy(const NoCopy &) = delete;
|
||||||
NoCopy &operator=(NoCopy const &) = default;
|
NoCopy &operator=(const NoCopy &) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NothrowCopy {
|
struct NothrowCopy {
|
||||||
NothrowCopy(NothrowCopy const &) noexcept = default;
|
NothrowCopy(const NothrowCopy &) noexcept = default;
|
||||||
NothrowCopy &operator=(NothrowCopy const &) noexcept = default;
|
NothrowCopy &operator=(const NothrowCopy &) noexcept = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CopyOnly {
|
struct CopyOnly {
|
||||||
CopyOnly(CopyOnly const &) = default;
|
CopyOnly(const CopyOnly &) = default;
|
||||||
CopyOnly(CopyOnly &&) = delete;
|
CopyOnly(CopyOnly &&) = delete;
|
||||||
CopyOnly &operator=(CopyOnly const &) = default;
|
CopyOnly &operator=(const CopyOnly &) = default;
|
||||||
CopyOnly &operator=(CopyOnly &&) = delete;
|
CopyOnly &operator=(CopyOnly &&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MoveOnly {
|
struct MoveOnly {
|
||||||
MoveOnly(MoveOnly const &) = delete;
|
MoveOnly(const MoveOnly &) = delete;
|
||||||
MoveOnly(MoveOnly &&) = default;
|
MoveOnly(MoveOnly &&) = default;
|
||||||
MoveOnly &operator=(MoveOnly const &) = default;
|
MoveOnly &operator=(const MoveOnly &) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MoveOnlyNT {
|
struct MoveOnlyNT {
|
||||||
MoveOnlyNT(MoveOnlyNT const &) = delete;
|
MoveOnlyNT(const MoveOnlyNT &) = delete;
|
||||||
MoveOnlyNT(MoveOnlyNT &&) {}
|
MoveOnlyNT(MoveOnlyNT &&) {}
|
||||||
MoveOnlyNT &operator=(MoveOnlyNT const &) = default;
|
MoveOnlyNT &operator=(const MoveOnlyNT &) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CopyAssign {
|
struct CopyAssign {
|
||||||
@@ -62,7 +62,7 @@ struct CopyAssign {
|
|||||||
copy_construct = copy_assign = move_construct = move_assign = alive = 0;
|
copy_construct = copy_assign = move_construct = move_assign = alive = 0;
|
||||||
}
|
}
|
||||||
CopyAssign(int v) : value(v) { ++alive; }
|
CopyAssign(int v) : value(v) { ++alive; }
|
||||||
CopyAssign(CopyAssign const &o) : value(o.value) {
|
CopyAssign(const CopyAssign &o) : value(o.value) {
|
||||||
++alive;
|
++alive;
|
||||||
++copy_construct;
|
++copy_construct;
|
||||||
}
|
}
|
||||||
@@ -71,7 +71,7 @@ struct CopyAssign {
|
|||||||
++alive;
|
++alive;
|
||||||
++move_construct;
|
++move_construct;
|
||||||
}
|
}
|
||||||
CopyAssign &operator=(CopyAssign const &o) {
|
CopyAssign &operator=(const CopyAssign &o) {
|
||||||
value = o.value;
|
value = o.value;
|
||||||
++copy_assign;
|
++copy_assign;
|
||||||
return *this;
|
return *this;
|
||||||
@@ -93,27 +93,27 @@ int CopyAssign::move_construct = 0;
|
|||||||
int CopyAssign::move_assign = 0;
|
int CopyAssign::move_assign = 0;
|
||||||
|
|
||||||
struct CopyMaybeThrows {
|
struct CopyMaybeThrows {
|
||||||
CopyMaybeThrows(CopyMaybeThrows const &);
|
CopyMaybeThrows(const CopyMaybeThrows &);
|
||||||
CopyMaybeThrows &operator=(CopyMaybeThrows const &);
|
CopyMaybeThrows &operator=(const CopyMaybeThrows &);
|
||||||
};
|
};
|
||||||
struct CopyDoesThrow {
|
struct CopyDoesThrow {
|
||||||
CopyDoesThrow(CopyDoesThrow const &) noexcept(false);
|
CopyDoesThrow(const CopyDoesThrow &) noexcept(false);
|
||||||
CopyDoesThrow &operator=(CopyDoesThrow const &) noexcept(false);
|
CopyDoesThrow &operator=(const CopyDoesThrow &) noexcept(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||||
struct CopyThrows {
|
struct CopyThrows {
|
||||||
CopyThrows() = default;
|
CopyThrows() = default;
|
||||||
CopyThrows(CopyThrows const &) { throw 42; }
|
CopyThrows(const CopyThrows &) { throw 42; }
|
||||||
CopyThrows &operator=(CopyThrows const &) { throw 42; }
|
CopyThrows &operator=(const CopyThrows &) { throw 42; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MoveThrows {
|
struct MoveThrows {
|
||||||
static int alive;
|
static int alive;
|
||||||
MoveThrows() { ++alive; }
|
MoveThrows() { ++alive; }
|
||||||
MoveThrows(MoveThrows const &) { ++alive; }
|
MoveThrows(const MoveThrows &) { ++alive; }
|
||||||
MoveThrows(MoveThrows &&) { throw 42; }
|
MoveThrows(MoveThrows &&) { throw 42; }
|
||||||
MoveThrows &operator=(MoveThrows const &) { return *this; }
|
MoveThrows &operator=(const MoveThrows &) { return *this; }
|
||||||
MoveThrows &operator=(MoveThrows &&) { throw 42; }
|
MoveThrows &operator=(MoveThrows &&) { throw 42; }
|
||||||
~MoveThrows() { --alive; }
|
~MoveThrows() { --alive; }
|
||||||
};
|
};
|
||||||
@@ -123,13 +123,13 @@ int MoveThrows::alive = 0;
|
|||||||
struct MakeEmptyT {
|
struct MakeEmptyT {
|
||||||
static int alive;
|
static int alive;
|
||||||
MakeEmptyT() { ++alive; }
|
MakeEmptyT() { ++alive; }
|
||||||
MakeEmptyT(MakeEmptyT const &) {
|
MakeEmptyT(const MakeEmptyT &) {
|
||||||
++alive;
|
++alive;
|
||||||
// Don't throw from the copy constructor since variant's assignment
|
// Don't throw from the copy constructor since variant's assignment
|
||||||
// operator performs a copy before committing to the assignment.
|
// operator performs a copy before committing to the assignment.
|
||||||
}
|
}
|
||||||
MakeEmptyT(MakeEmptyT &&) { throw 42; }
|
MakeEmptyT(MakeEmptyT &&) { throw 42; }
|
||||||
MakeEmptyT &operator=(MakeEmptyT const &) { throw 42; }
|
MakeEmptyT &operator=(const MakeEmptyT &) { throw 42; }
|
||||||
MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
|
MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
|
||||||
~MakeEmptyT() { --alive; }
|
~MakeEmptyT() { --alive; }
|
||||||
};
|
};
|
||||||
@@ -164,7 +164,7 @@ void test_copy_assignment_sfinae() {
|
|||||||
static_assert(std::is_copy_assignable<V>::value, "");
|
static_assert(std::is_copy_assignable<V>::value, "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// variant only provides copy assignment when beth the copy and move
|
// variant only provides copy assignment when both the copy and move
|
||||||
// constructors are well formed
|
// constructors are well formed
|
||||||
using V = std::variant<int, CopyOnly>;
|
using V = std::variant<int, CopyOnly>;
|
||||||
static_assert(!std::is_copy_assignable<V>::value, "");
|
static_assert(!std::is_copy_assignable<V>::value, "");
|
||||||
|
|||||||
@@ -26,36 +26,36 @@
|
|||||||
#include "variant_test_helpers.hpp"
|
#include "variant_test_helpers.hpp"
|
||||||
|
|
||||||
struct NoCopy {
|
struct NoCopy {
|
||||||
NoCopy(NoCopy const &) = delete;
|
NoCopy(const NoCopy &) = delete;
|
||||||
NoCopy &operator=(NoCopy const &) = default;
|
NoCopy &operator=(const NoCopy &) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CopyOnly {
|
struct CopyOnly {
|
||||||
CopyOnly(CopyOnly const &) = default;
|
CopyOnly(const CopyOnly &) = default;
|
||||||
CopyOnly(CopyOnly &&) = delete;
|
CopyOnly(CopyOnly &&) = delete;
|
||||||
CopyOnly &operator=(CopyOnly const &) = default;
|
CopyOnly &operator=(const CopyOnly &) = default;
|
||||||
CopyOnly &operator=(CopyOnly &&) = delete;
|
CopyOnly &operator=(CopyOnly &&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MoveOnly {
|
struct MoveOnly {
|
||||||
MoveOnly(MoveOnly const &) = delete;
|
MoveOnly(const MoveOnly &) = delete;
|
||||||
MoveOnly(MoveOnly &&) = default;
|
MoveOnly(MoveOnly &&) = default;
|
||||||
MoveOnly &operator=(MoveOnly const &) = delete;
|
MoveOnly &operator=(const MoveOnly &) = delete;
|
||||||
MoveOnly &operator=(MoveOnly &&) = default;
|
MoveOnly &operator=(MoveOnly &&) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MoveOnlyNT {
|
struct MoveOnlyNT {
|
||||||
MoveOnlyNT(MoveOnlyNT const &) = delete;
|
MoveOnlyNT(const MoveOnlyNT &) = delete;
|
||||||
MoveOnlyNT(MoveOnlyNT &&) {}
|
MoveOnlyNT(MoveOnlyNT &&) {}
|
||||||
MoveOnlyNT &operator=(MoveOnlyNT const &) = delete;
|
MoveOnlyNT &operator=(const MoveOnlyNT &) = delete;
|
||||||
MoveOnlyNT &operator=(MoveOnlyNT &&) = default;
|
MoveOnlyNT &operator=(MoveOnlyNT &&) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MoveOnlyOddNothrow {
|
struct MoveOnlyOddNothrow {
|
||||||
MoveOnlyOddNothrow(MoveOnlyOddNothrow &&) noexcept(false) {}
|
MoveOnlyOddNothrow(MoveOnlyOddNothrow &&) noexcept(false) {}
|
||||||
MoveOnlyOddNothrow(MoveOnlyOddNothrow const &) = delete;
|
MoveOnlyOddNothrow(const MoveOnlyOddNothrow &) = delete;
|
||||||
MoveOnlyOddNothrow &operator=(MoveOnlyOddNothrow &&) noexcept = default;
|
MoveOnlyOddNothrow &operator=(MoveOnlyOddNothrow &&) noexcept = default;
|
||||||
MoveOnlyOddNothrow &operator=(MoveOnlyOddNothrow const &) = delete;
|
MoveOnlyOddNothrow &operator=(const MoveOnlyOddNothrow &) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MoveAssignOnly {
|
struct MoveAssignOnly {
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ void test_T_ctor_sfinae() {
|
|||||||
static_assert(!std::is_constructible<V, int>::value, "ambiguous");
|
static_assert(!std::is_constructible<V, int>::value, "ambiguous");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int, int const &>;
|
using V = std::variant<int, const int &>;
|
||||||
static_assert(!std::is_constructible<V, int>::value, "ambiguous");
|
static_assert(!std::is_constructible<V, int>::value, "ambiguous");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -87,7 +87,7 @@ void test_T_ctor_basic() {
|
|||||||
}
|
}
|
||||||
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
||||||
{
|
{
|
||||||
using V = std::variant<int const &, int &&, long>;
|
using V = std::variant<const int &, int &&, long>;
|
||||||
static_assert(std::is_convertible<int &, V>::value, "must be implicit");
|
static_assert(std::is_convertible<int &, V>::value, "must be implicit");
|
||||||
int x = 42;
|
int x = 42;
|
||||||
V v(x);
|
V v(x);
|
||||||
@@ -95,7 +95,7 @@ void test_T_ctor_basic() {
|
|||||||
assert(&std::get<0>(v) == &x);
|
assert(&std::get<0>(v) == &x);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
using V = std::variant<int const &, int &&, long>;
|
using V = std::variant<const int &, int &&, long>;
|
||||||
static_assert(std::is_convertible<int, V>::value, "must be implicit");
|
static_assert(std::is_convertible<int, V>::value, "must be implicit");
|
||||||
int x = 42;
|
int x = 42;
|
||||||
V v(std::move(x));
|
V v(std::move(x));
|
||||||
|
|||||||
@@ -24,22 +24,22 @@
|
|||||||
|
|
||||||
struct NonT {
|
struct NonT {
|
||||||
NonT(int v) : value(v) {}
|
NonT(int v) : value(v) {}
|
||||||
NonT(NonT const &o) : value(o.value) {}
|
NonT(const NonT &o) : value(o.value) {}
|
||||||
int value;
|
int value;
|
||||||
};
|
};
|
||||||
static_assert(!std::is_trivially_copy_constructible<NonT>::value, "");
|
static_assert(!std::is_trivially_copy_constructible<NonT>::value, "");
|
||||||
|
|
||||||
struct NoCopy {
|
struct NoCopy {
|
||||||
NoCopy(NoCopy const &) = delete;
|
NoCopy(const NoCopy &) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MoveOnly {
|
struct MoveOnly {
|
||||||
MoveOnly(MoveOnly const &) = delete;
|
MoveOnly(const MoveOnly &) = delete;
|
||||||
MoveOnly(MoveOnly &&) = default;
|
MoveOnly(MoveOnly &&) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MoveOnlyNT {
|
struct MoveOnlyNT {
|
||||||
MoveOnlyNT(MoveOnlyNT const &) = delete;
|
MoveOnlyNT(const MoveOnlyNT &) = delete;
|
||||||
MoveOnlyNT(MoveOnlyNT &&) {}
|
MoveOnlyNT(MoveOnlyNT &&) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -47,13 +47,13 @@ struct MoveOnlyNT {
|
|||||||
struct MakeEmptyT {
|
struct MakeEmptyT {
|
||||||
static int alive;
|
static int alive;
|
||||||
MakeEmptyT() { ++alive; }
|
MakeEmptyT() { ++alive; }
|
||||||
MakeEmptyT(MakeEmptyT const &) {
|
MakeEmptyT(const MakeEmptyT &) {
|
||||||
++alive;
|
++alive;
|
||||||
// Don't throw from the copy constructor since variant's assignment
|
// Don't throw from the copy constructor since variant's assignment
|
||||||
// operator performs a copy before committing to the assignment.
|
// operator performs a copy before committing to the assignment.
|
||||||
}
|
}
|
||||||
MakeEmptyT(MakeEmptyT &&) { throw 42; }
|
MakeEmptyT(MakeEmptyT &&) { throw 42; }
|
||||||
MakeEmptyT &operator=(MakeEmptyT const &) { throw 42; }
|
MakeEmptyT &operator=(const MakeEmptyT &) { throw 42; }
|
||||||
MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
|
MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
|
||||||
~MakeEmptyT() { --alive; }
|
~MakeEmptyT() { --alive; }
|
||||||
};
|
};
|
||||||
@@ -124,7 +124,7 @@ void test_copy_ctor_valueless_by_exception() {
|
|||||||
using V = std::variant<int, MakeEmptyT>;
|
using V = std::variant<int, MakeEmptyT>;
|
||||||
V v1;
|
V v1;
|
||||||
makeEmpty(v1);
|
makeEmpty(v1);
|
||||||
V const &cv1 = v1;
|
const V &cv1 = v1;
|
||||||
V v(cv1);
|
V v(cv1);
|
||||||
assert(v.valueless_by_exception());
|
assert(v.valueless_by_exception());
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ void test_default_ctor_throws() {
|
|||||||
try {
|
try {
|
||||||
V v;
|
V v;
|
||||||
assert(false);
|
assert(false);
|
||||||
} catch (int const &ex) {
|
} catch (const int &ex) {
|
||||||
assert(ex == 42);
|
assert(ex == 42);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
assert(false);
|
assert(false);
|
||||||
|
|||||||
@@ -28,20 +28,20 @@ struct ThrowsMove {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct NoCopy {
|
struct NoCopy {
|
||||||
NoCopy(NoCopy const &) = delete;
|
NoCopy(const NoCopy &) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MoveOnly {
|
struct MoveOnly {
|
||||||
int value;
|
int value;
|
||||||
MoveOnly(int v) : value(v) {}
|
MoveOnly(int v) : value(v) {}
|
||||||
MoveOnly(MoveOnly const &) = delete;
|
MoveOnly(const MoveOnly &) = delete;
|
||||||
MoveOnly(MoveOnly &&) = default;
|
MoveOnly(MoveOnly &&) = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MoveOnlyNT {
|
struct MoveOnlyNT {
|
||||||
int value;
|
int value;
|
||||||
MoveOnlyNT(int v) : value(v) {}
|
MoveOnlyNT(int v) : value(v) {}
|
||||||
MoveOnlyNT(MoveOnlyNT const &) = delete;
|
MoveOnlyNT(const MoveOnlyNT &) = delete;
|
||||||
MoveOnlyNT(MoveOnlyNT &&other) : value(other.value) { other.value = -1; }
|
MoveOnlyNT(MoveOnlyNT &&other) : value(other.value) { other.value = -1; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -49,13 +49,13 @@ struct MoveOnlyNT {
|
|||||||
struct MakeEmptyT {
|
struct MakeEmptyT {
|
||||||
static int alive;
|
static int alive;
|
||||||
MakeEmptyT() { ++alive; }
|
MakeEmptyT() { ++alive; }
|
||||||
MakeEmptyT(MakeEmptyT const &) {
|
MakeEmptyT(const MakeEmptyT &) {
|
||||||
++alive;
|
++alive;
|
||||||
// Don't throw from the copy constructor since variant's assignment
|
// Don't throw from the copy constructor since variant's assignment
|
||||||
// operator performs a copy before committing to the assignment.
|
// operator performs a copy before committing to the assignment.
|
||||||
}
|
}
|
||||||
MakeEmptyT(MakeEmptyT &&) { throw 42; }
|
MakeEmptyT(MakeEmptyT &&) { throw 42; }
|
||||||
MakeEmptyT &operator=(MakeEmptyT const &) { throw 42; }
|
MakeEmptyT &operator=(const MakeEmptyT &) { throw 42; }
|
||||||
MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
|
MakeEmptyT &operator=(MakeEmptyT &&) { throw 42; }
|
||||||
~MakeEmptyT() { --alive; }
|
~MakeEmptyT() { --alive; }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ int NonTDtor1::count = 0;
|
|||||||
static_assert(!std::is_trivially_destructible<NonTDtor1>::value, "");
|
static_assert(!std::is_trivially_destructible<NonTDtor1>::value, "");
|
||||||
|
|
||||||
struct TDtor {
|
struct TDtor {
|
||||||
TDtor(TDtor const &) {} // non-trivial copy
|
TDtor(const TDtor &) {} // non-trivial copy
|
||||||
~TDtor() = default;
|
~TDtor() = default;
|
||||||
};
|
};
|
||||||
static_assert(!std::is_trivially_copy_constructible<TDtor>::value, "");
|
static_assert(!std::is_trivially_copy_constructible<TDtor>::value, "");
|
||||||
|
|||||||
@@ -58,14 +58,14 @@ void test_emplace_sfinae() {
|
|||||||
}
|
}
|
||||||
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
||||||
{
|
{
|
||||||
using V = std::variant<int, int &, int const &, int &&, TestTypes::NoCtors>;
|
using V = std::variant<int, int &, const int &, int &&, TestTypes::NoCtors>;
|
||||||
static_assert(emplace_exists<V, 0>(), "");
|
static_assert(emplace_exists<V, 0>(), "");
|
||||||
static_assert(emplace_exists<V, 0, int>(), "");
|
static_assert(emplace_exists<V, 0, int>(), "");
|
||||||
static_assert(emplace_exists<V, 0, long long>(), "");
|
static_assert(emplace_exists<V, 0, long long>(), "");
|
||||||
static_assert(!emplace_exists<V, 0, int, int>(), "too many args");
|
static_assert(!emplace_exists<V, 0, int, int>(), "too many args");
|
||||||
static_assert(emplace_exists<V, 1, int &>(), "");
|
static_assert(emplace_exists<V, 1, int &>(), "");
|
||||||
static_assert(!emplace_exists<V, 1>(), "cannot default construct ref");
|
static_assert(!emplace_exists<V, 1>(), "cannot default construct ref");
|
||||||
static_assert(!emplace_exists<V, 1, int const &>(), "cannot bind ref");
|
static_assert(!emplace_exists<V, 1, const int &>(), "cannot bind ref");
|
||||||
static_assert(!emplace_exists<V, 1, int &&>(), "cannot bind ref");
|
static_assert(!emplace_exists<V, 1, int &&>(), "cannot bind ref");
|
||||||
static_assert(emplace_exists<V, 2, int &>(), "");
|
static_assert(emplace_exists<V, 2, int &>(), "");
|
||||||
static_assert(emplace_exists<V, 2, const int &>(), "");
|
static_assert(emplace_exists<V, 2, const int &>(), "");
|
||||||
@@ -74,8 +74,8 @@ void test_emplace_sfinae() {
|
|||||||
"not constructible from void*");
|
"not constructible from void*");
|
||||||
static_assert(emplace_exists<V, 3, int>(), "");
|
static_assert(emplace_exists<V, 3, int>(), "");
|
||||||
static_assert(!emplace_exists<V, 3, int &>(), "cannot bind ref");
|
static_assert(!emplace_exists<V, 3, int &>(), "cannot bind ref");
|
||||||
static_assert(!emplace_exists<V, 3, int const &>(), "cannot bind ref");
|
static_assert(!emplace_exists<V, 3, const int &>(), "cannot bind ref");
|
||||||
static_assert(!emplace_exists<V, 3, int const &&>(), "cannot bind ref");
|
static_assert(!emplace_exists<V, 3, const int &&>(), "cannot bind ref");
|
||||||
static_assert(!emplace_exists<V, 4>(), "no ctors");
|
static_assert(!emplace_exists<V, 4>(), "no ctors");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -106,7 +106,7 @@ void test_basic() {
|
|||||||
}
|
}
|
||||||
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long, int const &, int &&, TestTypes::NoCtors,
|
using V = std::variant<int, long, const int &, int &&, TestTypes::NoCtors,
|
||||||
std::string>;
|
std::string>;
|
||||||
const int x = 100;
|
const int x = 100;
|
||||||
int y = 42;
|
int y = 42;
|
||||||
|
|||||||
@@ -52,12 +52,12 @@ void test_emplace_sfinae() {
|
|||||||
static_assert(!emplace_exists<V, void *, int>(), "cannot construct");
|
static_assert(!emplace_exists<V, void *, int>(), "cannot construct");
|
||||||
static_assert(emplace_exists<V, void *, int *>(), "");
|
static_assert(emplace_exists<V, void *, int *>(), "");
|
||||||
static_assert(!emplace_exists<V, void *, const int *>(), "");
|
static_assert(!emplace_exists<V, void *, const int *>(), "");
|
||||||
static_assert(emplace_exists<V, void const *, const int *>(), "");
|
static_assert(emplace_exists<V, const void *, const int *>(), "");
|
||||||
static_assert(emplace_exists<V, void const *, int *>(), "");
|
static_assert(emplace_exists<V, const void *, int *>(), "");
|
||||||
static_assert(!emplace_exists<V, TestTypes::NoCtors>(), "cannot construct");
|
static_assert(!emplace_exists<V, TestTypes::NoCtors>(), "cannot construct");
|
||||||
}
|
}
|
||||||
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
||||||
using V = std::variant<int, int &, int const &, int &&, long, long,
|
using V = std::variant<int, int &, const int &, int &&, long, long,
|
||||||
TestTypes::NoCtors>;
|
TestTypes::NoCtors>;
|
||||||
static_assert(emplace_exists<V, int>(), "");
|
static_assert(emplace_exists<V, int>(), "");
|
||||||
static_assert(emplace_exists<V, int, int>(), "");
|
static_assert(emplace_exists<V, int, int>(), "");
|
||||||
@@ -65,17 +65,17 @@ void test_emplace_sfinae() {
|
|||||||
static_assert(!emplace_exists<V, int, int, int>(), "too many args");
|
static_assert(!emplace_exists<V, int, int, int>(), "too many args");
|
||||||
static_assert(emplace_exists<V, int &, int &>(), "");
|
static_assert(emplace_exists<V, int &, int &>(), "");
|
||||||
static_assert(!emplace_exists<V, int &>(), "cannot default construct ref");
|
static_assert(!emplace_exists<V, int &>(), "cannot default construct ref");
|
||||||
static_assert(!emplace_exists<V, int &, int const &>(), "cannot bind ref");
|
static_assert(!emplace_exists<V, int &, const int &>(), "cannot bind ref");
|
||||||
static_assert(!emplace_exists<V, int &, int &&>(), "cannot bind ref");
|
static_assert(!emplace_exists<V, int &, int &&>(), "cannot bind ref");
|
||||||
static_assert(emplace_exists<V, int const &, int &>(), "");
|
static_assert(emplace_exists<V, const int &, int &>(), "");
|
||||||
static_assert(emplace_exists<V, int const &, const int &>(), "");
|
static_assert(emplace_exists<V, const int &, const int &>(), "");
|
||||||
static_assert(emplace_exists<V, int const &, int &&>(), "");
|
static_assert(emplace_exists<V, const int &, int &&>(), "");
|
||||||
static_assert(!emplace_exists<V, int const &, void *>(),
|
static_assert(!emplace_exists<V, const int &, void *>(),
|
||||||
"not constructible from void*");
|
"not constructible from void*");
|
||||||
static_assert(emplace_exists<V, int &&, int>(), "");
|
static_assert(emplace_exists<V, int &&, int>(), "");
|
||||||
static_assert(!emplace_exists<V, int &&, int &>(), "cannot bind ref");
|
static_assert(!emplace_exists<V, int &&, int &>(), "cannot bind ref");
|
||||||
static_assert(!emplace_exists<V, int &&, int const &>(), "cannot bind ref");
|
static_assert(!emplace_exists<V, int &&, const int &>(), "cannot bind ref");
|
||||||
static_assert(!emplace_exists<V, int &&, int const &&>(), "cannot bind ref");
|
static_assert(!emplace_exists<V, int &&, const int &&>(), "cannot bind ref");
|
||||||
static_assert(!emplace_exists<V, long, long>(), "ambiguous");
|
static_assert(!emplace_exists<V, long, long>(), "ambiguous");
|
||||||
static_assert(!emplace_exists<V, TestTypes::NoCtors>(),
|
static_assert(!emplace_exists<V, TestTypes::NoCtors>(),
|
||||||
"cannot construct void");
|
"cannot construct void");
|
||||||
@@ -107,7 +107,7 @@ void test_basic() {
|
|||||||
}
|
}
|
||||||
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
#if !defined(TEST_VARIANT_HAS_NO_REFERENCES)
|
||||||
{
|
{
|
||||||
using V = std::variant<int, long, int const &, int &&, TestTypes::NoCtors,
|
using V = std::variant<int, long, const int &, int &&, TestTypes::NoCtors,
|
||||||
std::string>;
|
std::string>;
|
||||||
const int x = 100;
|
const int x = 100;
|
||||||
int y = 42;
|
int y = 42;
|
||||||
@@ -117,8 +117,8 @@ void test_basic() {
|
|||||||
v.emplace<long>();
|
v.emplace<long>();
|
||||||
assert(std::get<long>(v) == 0);
|
assert(std::get<long>(v) == 0);
|
||||||
// emplace a reference
|
// emplace a reference
|
||||||
v.emplace<int const &>(x);
|
v.emplace<const int &>(x);
|
||||||
assert(&std::get<int const &>(v) == &x);
|
assert(&std::get<const int &>(v) == &x);
|
||||||
// emplace an rvalue reference
|
// emplace an rvalue reference
|
||||||
v.emplace<int &&>(std::move(y));
|
v.emplace<int &&>(std::move(y));
|
||||||
assert(&std::get<int &&>(v) == &y);
|
assert(&std::get<int &&>(v) == &y);
|
||||||
|
|||||||
@@ -30,14 +30,14 @@ void swap(NotSwappable &, NotSwappable &) = delete;
|
|||||||
|
|
||||||
struct NotCopyable {
|
struct NotCopyable {
|
||||||
NotCopyable() = default;
|
NotCopyable() = default;
|
||||||
NotCopyable(NotCopyable const &) = delete;
|
NotCopyable(const NotCopyable &) = delete;
|
||||||
NotCopyable &operator=(NotCopyable const &) = delete;
|
NotCopyable &operator=(const NotCopyable &) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct NotCopyableWithSwap {
|
struct NotCopyableWithSwap {
|
||||||
NotCopyableWithSwap() = default;
|
NotCopyableWithSwap() = default;
|
||||||
NotCopyableWithSwap(NotCopyableWithSwap const &) = delete;
|
NotCopyableWithSwap(const NotCopyableWithSwap &) = delete;
|
||||||
NotCopyableWithSwap &operator=(NotCopyableWithSwap const &) = delete;
|
NotCopyableWithSwap &operator=(const NotCopyableWithSwap &) = delete;
|
||||||
};
|
};
|
||||||
void swap(NotCopyableWithSwap &, NotCopyableWithSwap) {}
|
void swap(NotCopyableWithSwap &, NotCopyableWithSwap) {}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ struct NothrowTypeImp {
|
|||||||
static void reset() { move_called = move_assign_called = swap_called = 0; }
|
static void reset() { move_called = move_assign_called = swap_called = 0; }
|
||||||
NothrowTypeImp() = default;
|
NothrowTypeImp() = default;
|
||||||
explicit NothrowTypeImp(int v) : value(v) {}
|
explicit NothrowTypeImp(int v) : value(v) {}
|
||||||
NothrowTypeImp(NothrowTypeImp const &o) noexcept(NT_Copy) : value(o.value) {
|
NothrowTypeImp(const NothrowTypeImp &o) noexcept(NT_Copy) : value(o.value) {
|
||||||
assert(false);
|
assert(false);
|
||||||
} // never called by test
|
} // never called by test
|
||||||
NothrowTypeImp(NothrowTypeImp &&o) noexcept(NT_Move) : value(o.value) {
|
NothrowTypeImp(NothrowTypeImp &&o) noexcept(NT_Move) : value(o.value) {
|
||||||
@@ -81,7 +81,7 @@ struct NothrowTypeImp {
|
|||||||
do_throw<!NT_Move>();
|
do_throw<!NT_Move>();
|
||||||
o.value = -1;
|
o.value = -1;
|
||||||
}
|
}
|
||||||
NothrowTypeImp &operator=(NothrowTypeImp const &) noexcept(NT_CopyAssign) {
|
NothrowTypeImp &operator=(const NothrowTypeImp &) noexcept(NT_CopyAssign) {
|
||||||
assert(false);
|
assert(false);
|
||||||
return *this;
|
return *this;
|
||||||
} // never called by the tests
|
} // never called by the tests
|
||||||
|
|||||||
@@ -23,6 +23,6 @@ int main()
|
|||||||
{
|
{
|
||||||
// expected-error@variant:* 3 {{static_assert failed}}
|
// expected-error@variant:* 3 {{static_assert failed}}
|
||||||
std::variant<int, int&> v; // expected-note {{requested here}}
|
std::variant<int, int&> v; // expected-note {{requested here}}
|
||||||
std::variant<int, int const&> v2; // expected-note {{requested here}}
|
std::variant<int, const int &> v2; // expected-note {{requested here}}
|
||||||
std::variant<int, int&&> v3; // expected-note {{requested here}}
|
std::variant<int, int&&> v3; // expected-note {{requested here}}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,16 +77,16 @@ struct ForwardingCallObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static CallType last_call_type;
|
static CallType last_call_type;
|
||||||
static TypeID const *last_call_args;
|
static const TypeID *last_call_args;
|
||||||
};
|
};
|
||||||
|
|
||||||
CallType ForwardingCallObject::last_call_type = CT_None;
|
CallType ForwardingCallObject::last_call_type = CT_None;
|
||||||
TypeID const *ForwardingCallObject::last_call_args = nullptr;
|
const TypeID *ForwardingCallObject::last_call_args = nullptr;
|
||||||
|
|
||||||
void test_call_operator_forwarding() {
|
void test_call_operator_forwarding() {
|
||||||
using Fn = ForwardingCallObject;
|
using Fn = ForwardingCallObject;
|
||||||
Fn obj{};
|
Fn obj{};
|
||||||
Fn const &cobj = obj;
|
const Fn &cobj = obj;
|
||||||
{ // test call operator forwarding - single variant, single arg
|
{ // test call operator forwarding - single variant, single arg
|
||||||
using V = std::variant<int>;
|
using V = std::variant<int>;
|
||||||
V v(42);
|
V v(42);
|
||||||
@@ -134,11 +134,11 @@ void test_argument_forwarding() {
|
|||||||
{ // single argument - value type
|
{ // single argument - value type
|
||||||
using V = std::variant<int>;
|
using V = std::variant<int>;
|
||||||
V v(42);
|
V v(42);
|
||||||
V const &cv = v;
|
const V &cv = v;
|
||||||
std::visit(obj, v);
|
std::visit(obj, v);
|
||||||
assert(Fn::check_call<int &>(Val));
|
assert(Fn::check_call<int &>(Val));
|
||||||
std::visit(obj, cv);
|
std::visit(obj, cv);
|
||||||
assert(Fn::check_call<int const &>(Val));
|
assert(Fn::check_call<const int &>(Val));
|
||||||
std::visit(obj, std::move(v));
|
std::visit(obj, std::move(v));
|
||||||
assert(Fn::check_call<int &&>(Val));
|
assert(Fn::check_call<int &&>(Val));
|
||||||
std::visit(obj, std::move(cv));
|
std::visit(obj, std::move(cv));
|
||||||
@@ -149,7 +149,7 @@ void test_argument_forwarding() {
|
|||||||
using V = std::variant<int &>;
|
using V = std::variant<int &>;
|
||||||
int x = 42;
|
int x = 42;
|
||||||
V v(x);
|
V v(x);
|
||||||
V const &cv = v;
|
const V &cv = v;
|
||||||
std::visit(obj, v);
|
std::visit(obj, v);
|
||||||
assert(Fn::check_call<int &>(Val));
|
assert(Fn::check_call<int &>(Val));
|
||||||
std::visit(obj, cv);
|
std::visit(obj, cv);
|
||||||
@@ -163,7 +163,7 @@ void test_argument_forwarding() {
|
|||||||
using V = std::variant<int &&>;
|
using V = std::variant<int &&>;
|
||||||
int x = 42;
|
int x = 42;
|
||||||
V v(std::move(x));
|
V v(std::move(x));
|
||||||
V const &cv = v;
|
const V &cv = v;
|
||||||
std::visit(obj, v);
|
std::visit(obj, v);
|
||||||
assert(Fn::check_call<int &>(Val));
|
assert(Fn::check_call<int &>(Val));
|
||||||
std::visit(obj, cv);
|
std::visit(obj, cv);
|
||||||
@@ -174,16 +174,16 @@ void test_argument_forwarding() {
|
|||||||
assert(Fn::check_call<int &&>(Val));
|
assert(Fn::check_call<int &&>(Val));
|
||||||
}
|
}
|
||||||
{ // multi argument - multi variant
|
{ // multi argument - multi variant
|
||||||
using S = std::string const &;
|
using S = const std::string &;
|
||||||
using V = std::variant<int, S, long &&>;
|
using V = std::variant<int, S, long &&>;
|
||||||
std::string const str = "hello";
|
const std::string str = "hello";
|
||||||
long l = 43;
|
long l = 43;
|
||||||
V v1(42);
|
V v1(42);
|
||||||
V const &cv1 = v1;
|
const V &cv1 = v1;
|
||||||
V v2(str);
|
V v2(str);
|
||||||
V const &cv2 = v2;
|
const V &cv2 = v2;
|
||||||
V v3(std::move(l));
|
V v3(std::move(l));
|
||||||
V const &cv3 = v3;
|
const V &cv3 = v3;
|
||||||
std::visit(obj, v1, v2, v3);
|
std::visit(obj, v1, v2, v3);
|
||||||
assert((Fn::check_call<int &, S, long &>(Val)));
|
assert((Fn::check_call<int &, S, long &>(Val)));
|
||||||
std::visit(obj, cv1, cv2, std::move(v3));
|
std::visit(obj, cv1, cv2, std::move(v3));
|
||||||
@@ -243,7 +243,7 @@ void test_exceptions() {
|
|||||||
auto test = [&](auto &&... args) {
|
auto test = [&](auto &&... args) {
|
||||||
try {
|
try {
|
||||||
std::visit(obj, args...);
|
std::visit(obj, args...);
|
||||||
} catch (std::bad_variant_access const &) {
|
} catch (const std::bad_variant_access &) {
|
||||||
return true;
|
return true;
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user