|
|
- #pragma once
-
- #include "gp_config.hpp"
-
- #include <gp/algorithm/tmp_manip.hpp>
- #include "gp/allocator/dummy.hpp"
- #include "gp/exception.hpp"
- #include "gp/function.hpp"
- #include "gp/memory.hpp"
-
- #include <type_traits>
- #include <new>
-
-
- namespace gp{
-
- template<typename ...T>
- class fixed_variant final {
- std::size_t index = std::numeric_limits<std::size_t>::max();
- char buffer[max_size<T...>()];
- gp::function<void(void*, void*)> cpytor = [](void*, void*){};
- gp::function<void(void*, void*)> mvtor = [](void*, void*){};
- 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(void*)>([](void* thing){((U*)thing)->~U();});
- cpytor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(*(U*)src);});
- mvtor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));});
- }
-
- 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(void*)>([](void* thing){((U*)thing)->~U();});
- cpytor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(*(U*)src);});
- mvtor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));});
- }
-
- constexpr fixed_variant(fixed_variant& oth)
- : index{oth.index}
- , dtor{oth.dtor}
- , cpytor{oth.cpytor}
- , mvtor{oth.mvtor}
- {
- cpytor(oth.buffer, buffer);
- }
-
- template<typename U>
- constexpr size_t alt() const {
- return r_index_of<U, T...>::value;
- }
-
- size_t type() const {
- return index;
- }
-
- void operator=(fixed_variant& value)
- {
- if(index != std::numeric_limits<std::size_t>::max())
- {
- dtor((void*)buffer);
- }
- index = value.index;
- cpytor = value.cpytor;
- dtor = value.dtor;
- mvtor(value.buffer, buffer);
- }
-
- 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();});
- cpytor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(*(U*)src);});
- mvtor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));});
- }
-
- 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();});
- cpytor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(*(U*)src);});
- mvtor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));});
- }
-
- ~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;
- }
- }
- };*/
- }
|