General Purpose library for Freestanding C++ and POSIX systems
25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.
 
 

181 satır
4.5 KiB

#pragma once
#include <gp/algorithm/tmp_manip.hpp>
#include <type_traits>
#include <new>
#include "gp_config.hpp"
#include "gp/exception.hpp"
#include "gp/memory.hpp"
#include "gp/function.hpp"
namespace gp{
template<typename ...T>
class fixed_variant{
std::size_t index = std::numeric_limits<std::size_t>::max();
char buffer[max_size<T...>()];
gp::function<void(void*)> dtor = [](void*){};
static_assert(all_of_fixed_size<T...>::value, "not fixed");
public:
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
constexpr fixed_variant(U& value)
: index{r_index_of<U, T...>::value}
{
new(buffer) U(value);
dtor = gp::function([](void* thing){((U*)thing)->~U();});
}
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
constexpr fixed_variant(U&& value)
: index{r_index_of<U, T...>::value}
{
new(buffer) U(std::move(value));
dtor = gp::function([](void* thing){((U*)thing)->~U();});
}
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
void operator=(U& value)
{
if(index != std::numeric_limits<std::size_t>::max())
{
dtor((void*)buffer);
}
index = r_index_of<U, T...>::value;
new(buffer) U(value);
dtor = gp::function([](void* thing){((U*)thing)->~U();});
}
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
void operator=(U&& value)
{
if(index != std::numeric_limits<std::size_t>::max())
{
dtor((void*)buffer);
}
index = r_index_of<U, T...>::value;
new(buffer) U(std::move(value));
dtor = gp::function([](void* thing){((U*)thing)->~U();});
}
~fixed_variant()
{
if(index != std::numeric_limits<std::size_t>::max())
{
dtor((void*)buffer);
}
}
template<typename U>
constexpr U& value()
{
if constexpr (gp_config::has_exceptions)
{
if(r_index_of<U, T...>::value != index)
{
throw bad_variant_access<U>{};
}
}
return *reinterpret_cast<U*>(buffer);
}
template<typename U>
constexpr U& is_a()
{
if(r_index_of<U, T...>::value == index)
{
return true;
}
else
{
return false;
}
}
};
template<typename allocator_t = gp_config::memory_module::default_allocator, typename ...T>
class variant{
std::size_t index = std::numeric_limits<std::size_t>::max();
void* ptr;
gp::function<void(void*)> dtor = [](void*){};
allocator_t allocator;
public:
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
constexpr variant(U& value)
: index{r_index_of<U, T...>::value}
{
ptr = (void*)new(allocator.allocate(sizeof(U))) U(value);
dtor = gp::function([](void* thing){((U*)thing)->~U();}); // TODO:replae with delete(p,t)
}
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
constexpr variant(U&& value)
: index{r_index_of<U, T...>::value}
{
ptr = (void*)new(allocator.allocate(sizeof(U))) U(std::move(value));
dtor = gp::function([](void* thing){((U*)thing)->~U();}); // TODO:replae with delete(p,t)
}
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
void operator=(U& value)
{
if(index != std::numeric_limits<std::size_t>::max())
{
dtor(ptr);
allocator.deallocate(ptr);
}
index = r_index_of<U, T...>::value;
ptr = (void*)new(allocator.allocate(sizeof(U))) U(value);
dtor = gp::function([](void* thing){((U*)thing)->~U();}); // TODO:replae with delete(p,t)
}
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type>
void operator=(U&& value)
{
if(index != std::numeric_limits<std::size_t>::max())
{
dtor(ptr);
allocator.deallocate(ptr);
}
index = r_index_of<U, T...>::value;
ptr = (void*)new(allocator.allocate(sizeof(U))) U(std::move(value));
dtor = gp::function([](void* thing){((U*)thing)->~U();}); // TODO: replace with delete(p, t)
}
~variant()
{
if(index != std::numeric_limits<std::size_t>::max())
{
dtor(ptr);
allocator.deallocate(ptr);
}
}
template<typename U>
constexpr U& value()
{
if constexpr (gp_config::has_exceptions)
{
if(r_index_of<U, T...>::value != index)
{
throw bad_variant_access<U>{};
}
}
return *reinterpret_cast<U*>(ptr);
}
template<typename U>
constexpr U& is_a()
{
if(r_index_of<U, T...>::value == index)
{
return true;
}
else
{
return false;
}
}
};
}