cpp/variant/main.cpp

260 lines
6.2 KiB
C++
Raw Normal View History

2023-07-16 07:03:47 +00:00
#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;
}