cpp/variant/main.cpp
2023-07-16 10:03:47 +03:00

260 lines
6.2 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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