260 lines
6.2 KiB
C++
260 lines
6.2 KiB
C++
![]() |
#include <iostream>
|
|||
|
#include <cstring>
|
|||
|
#include <cassert>
|
|||
|
#include <vector>
|
|||
|
#include <variant>
|
|||
|
#include "variant.h"
|
|||
|
|
|||
|
using std::cin;
|
|||
|
using std::cout;
|
|||
|
using std::endl;
|
|||
|
|
|||
|
/*
|
|||
|
using std::get;
|
|||
|
using std::holds_alternative;
|
|||
|
template<typename... Types>
|
|||
|
using Variant = std::variant<Types...>;
|
|||
|
*/
|
|||
|
|
|||
|
struct A {
|
|||
|
A() {
|
|||
|
cout << "construct ()" << endl;
|
|||
|
}
|
|||
|
A(const A&) {
|
|||
|
cout << "construct (const A&)" << endl;
|
|||
|
}
|
|||
|
A(A&& a) {
|
|||
|
cout << "A(&&)" << endl;
|
|||
|
}
|
|||
|
A& operator=(const A&) {
|
|||
|
cout << "operator= (const A&)" << endl;
|
|||
|
return *this;
|
|||
|
}
|
|||
|
A& operator=(A&& another) {
|
|||
|
cout << "=&&" << endl;
|
|||
|
return *this;
|
|||
|
}
|
|||
|
~A() {
|
|||
|
cout << "~A()" << endl;
|
|||
|
}
|
|||
|
};
|
|||
|
|
|||
|
void compile_test() {
|
|||
|
int x;
|
|||
|
{
|
|||
|
Variant<int, double> v(1.0);
|
|||
|
const Variant<int, double> cv(1.0);
|
|||
|
Variant<std::vector<int>> vv;
|
|||
|
holds_alternative<double>(v);
|
|||
|
get<double>(v);
|
|||
|
get<double>(cv);
|
|||
|
static_assert(!std::is_assignable_v<decltype(v), std::vector<int>>);
|
|||
|
// static_assert(!std::is_assignable_v<decltype(vv), int>);
|
|||
|
static_assert(!std::is_assignable_v<Variant < float, int>, double > );
|
|||
|
static_assert(!std::is_assignable_v<decltype(get<double>(cv)), double>);
|
|||
|
static_assert(std::is_rvalue_reference_v<decltype(get<double>(std::move(v)))>);
|
|||
|
static_assert(std::is_lvalue_reference_v<decltype(get<double>(v))>);
|
|||
|
}
|
|||
|
{
|
|||
|
Variant<std::string> v = "abcdefgh";
|
|||
|
v = "lakjdflksd";
|
|||
|
v = std::string("alksdjfasf");
|
|||
|
Variant<std::string> vv("abcdefgh");
|
|||
|
assert(get<std::string>(vv).size() == 8);
|
|||
|
Variant<std::string, char, std::vector<int>> vvv = "abcdefgh";
|
|||
|
Variant<std::string, char, std::vector<int>> vvvv("abcdefgh");
|
|||
|
Variant<std::string> vvvvv(std::string("alskdjflaksf"));
|
|||
|
Variant<std::string> vvvvvv = std::string("alskdjflaksf");
|
|||
|
}
|
|||
|
{
|
|||
|
// У тебя должен быть
|
|||
|
// template<typename T, typename U, typename... Args>
|
|||
|
// void emplace(std::initializer_list<U>, Args&&...);
|
|||
|
//
|
|||
|
// https://en.cppreference.com/w/cpp/utility/variant/emplace
|
|||
|
using vec = std::vector<int>;
|
|||
|
Variant<vec> v;
|
|||
|
vec& a = v.emplace<std::vector<int>>({1, 2, 3});
|
|||
|
// Также долежн быть emplace по индексу
|
|||
|
vec& b = v.emplace<0>(std::vector<int>(2));
|
|||
|
// Также долежн быть emplace по индексу и std::initializer_list :)
|
|||
|
vec& c = v.emplace<0>({1, 2, 3});
|
|||
|
}
|
|||
|
{
|
|||
|
Variant<const int> v;
|
|||
|
// Пока хз как это решить
|
|||
|
// static_assert(!std::is_assignable_v<decltype(v), int>);
|
|||
|
// v = 10;
|
|||
|
}
|
|||
|
{
|
|||
|
Variant<const int, std::string, const std::string, double> v = 1;
|
|||
|
Variant<int, double> vvv = 1.0f;
|
|||
|
std::variant<int, double> vv = 1.0f;
|
|||
|
std::cout << std::is_constructible_v<int, float> << std::endl;
|
|||
|
}
|
|||
|
cout << "compile test passed" << endl;
|
|||
|
}
|
|||
|
|
|||
|
void test1() {
|
|||
|
int x;
|
|||
|
{
|
|||
|
const Variant<A, int> v(10);
|
|||
|
std::cout << get<int>(v) << std::endl;
|
|||
|
assert(get<int>(v) == 10);
|
|||
|
{
|
|||
|
int cnt_try = 0;
|
|||
|
try {
|
|||
|
get<A>(v);
|
|||
|
} catch (...) {
|
|||
|
cnt_try++;
|
|||
|
}
|
|||
|
try {
|
|||
|
get<0>(v);
|
|||
|
} catch (...) {
|
|||
|
cnt_try++;
|
|||
|
}
|
|||
|
assert(cnt_try == 2);
|
|||
|
}
|
|||
|
}
|
|||
|
{
|
|||
|
Variant<A, int> v(10);
|
|||
|
assert(get<int>(v) == 10);
|
|||
|
v = 11;
|
|||
|
assert(get<int>(v) == 11);
|
|||
|
get<int>(v)++;
|
|||
|
assert(get<int>(v) == 12);
|
|||
|
}
|
|||
|
{
|
|||
|
Variant<std::vector<int>> v;
|
|||
|
// assert(v.valueless_by_exception());
|
|||
|
}
|
|||
|
|
|||
|
cout << "test1 passed" << endl;
|
|||
|
}
|
|||
|
|
|||
|
void string_test() {
|
|||
|
Variant<std::string> v = "abcdefgh";
|
|||
|
assert(v.index() == 0);
|
|||
|
v = "lakjdflksd";
|
|||
|
assert(get<std::string>(v).size() == 10);
|
|||
|
assert(v.index() == 0);
|
|||
|
v = std::string("a");
|
|||
|
assert(get<std::string>(v).size() == 1);
|
|||
|
assert(v.index() == 0);
|
|||
|
Variant<std::string> vv("ab");
|
|||
|
assert(get<std::string>(vv).size() == 2);
|
|||
|
assert(vv.index() == 0);
|
|||
|
vv = "als";
|
|||
|
assert(get<std::string>(vv).size() == 3);
|
|||
|
assert(vv.index() == 0);
|
|||
|
vv = std::string("alsd");
|
|||
|
assert(get<std::string>(vv).size() == 4);
|
|||
|
assert(vv.index() == 0);
|
|||
|
Variant<std::string, char, std::vector<int>> vvv = "abcdefgh";
|
|||
|
assert(vvv.index() == 0);
|
|||
|
vvv = "alksjdgasg";
|
|||
|
assert(vvv.index() == 0);
|
|||
|
vvv = "alskdjglkagj";
|
|||
|
assert(vvv.index() == 0);
|
|||
|
Variant<std::string, char, std::vector<int>> vvvv("abcdefgh");
|
|||
|
assert(vvvv.index() == 0);
|
|||
|
vvvv = "asljgs;lgdk";
|
|||
|
assert(vvvv.index() == 0);
|
|||
|
vvvv = "al;kdja;k";
|
|||
|
assert(vvvv.index() == 0);
|
|||
|
Variant<std::string> vvvvv(std::string("alskdjflaksf"));
|
|||
|
assert(vvvvv.index() == 0);
|
|||
|
vvvvv = "a;kjga;g";
|
|||
|
assert(vvvvv.index() == 0);
|
|||
|
vvvvv = "asdjg;alkjg;alkjg";
|
|||
|
assert(vvvvv.index() == 0);
|
|||
|
Variant<std::string> vvvvvv = std::string("alskdjflaksf");
|
|||
|
assert(vvvvvv.index() == 0);
|
|||
|
vvvvvv = "askjga;j";
|
|||
|
assert(vvvvvv.index() == 0);
|
|||
|
vvvvvv = "a;lkjdg;aldjg";
|
|||
|
assert(vvvvvv.index() == 0);
|
|||
|
cout << "string test passed" << endl;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
int testConstr = 0;
|
|||
|
int testDestroy = 0;
|
|||
|
|
|||
|
template<size_t N>
|
|||
|
struct TestDelete {
|
|||
|
TestDelete() { testConstr++; }
|
|||
|
~TestDelete() { ++testDestroy; }
|
|||
|
};
|
|||
|
|
|||
|
int countDelete = 0;
|
|||
|
void operator delete[](void* ptr) {
|
|||
|
countDelete++;
|
|||
|
}
|
|||
|
void operator delete(void* ptr) {
|
|||
|
countDelete++;
|
|||
|
}
|
|||
|
|
|||
|
void test2() {
|
|||
|
countDelete = 0;
|
|||
|
{
|
|||
|
Variant<TestDelete<0>, TestDelete<1>, TestDelete<2>> v;
|
|||
|
}
|
|||
|
// assert(testDestroy == 1);
|
|||
|
assert(testConstr == 1);
|
|||
|
// assert(countDelete == 1);
|
|||
|
{
|
|||
|
std::variant<TestDelete<0>, TestDelete<1>, TestDelete<2>> v;
|
|||
|
v = TestDelete<1>();
|
|||
|
v = TestDelete<2>();
|
|||
|
}
|
|||
|
// assert(testDestroy == 6);
|
|||
|
assert(testConstr == 4);
|
|||
|
std::cout << countDelete << std::endl;
|
|||
|
// assert(countDelete == 2);
|
|||
|
std::cout << "test2 passed" << std::endl;
|
|||
|
}
|
|||
|
|
|||
|
void test3() {
|
|||
|
using VAR = Variant<std::string, int>;
|
|||
|
VAR x = "ddd";
|
|||
|
{
|
|||
|
VAR v("als");
|
|||
|
x = std::move(v);
|
|||
|
}
|
|||
|
std::cout << get<0>(x) << std::endl;
|
|||
|
assert(get<0>(x) == "als");
|
|||
|
std::cout << "test3 passed";
|
|||
|
}
|
|||
|
|
|||
|
void test4() {
|
|||
|
{
|
|||
|
Variant<const int, const double> v = 1.0;
|
|||
|
assert(v.index() == 1);
|
|||
|
}
|
|||
|
{
|
|||
|
Variant<const int, const double> v = 1.0f;
|
|||
|
assert(v.index() == 1);
|
|||
|
}
|
|||
|
{
|
|||
|
Variant<const int, const double> v = 1;
|
|||
|
assert(v.index() == 0);
|
|||
|
}
|
|||
|
{
|
|||
|
Variant<const int, const double> v = 'a';
|
|||
|
assert(v.index() == 0);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
int main() {
|
|||
|
compile_test();
|
|||
|
test1();
|
|||
|
string_test();
|
|||
|
test2();
|
|||
|
test3();
|
|||
|
test4();
|
|||
|
|
|||
|
// std::variant<int, int, double> v;
|
|||
|
// get<int>(v) = 10;
|
|||
|
}
|