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