|
|
@ -27,6 +27,10 @@ namespace gp{ |
|
|
|
gp::function<void(void*, void*)> cpytor = {[](void*, void*){}, nullopt}; |
|
|
|
gp::function<void(void*, void*)> mvtor = {[](void*, void*){}, nullopt}; |
|
|
|
gp::function<void(void*)> dtor = {[](void*){}, nullopt}; |
|
|
|
/**
|
|
|
|
* This is kinda bad, but stems from my inability to make gp::function work properly with constness |
|
|
|
*/ |
|
|
|
bool(*cmptor)(const void*, const void*) = +[](const void*, const void*) -> bool {return false;}; |
|
|
|
static_assert(all_of_fixed_size<T...>::value, "not fixed"); |
|
|
|
|
|
|
|
public: |
|
|
@ -55,6 +59,9 @@ namespace gp{ |
|
|
|
new(dest) actual(gp::move(*(actual*)src)); |
|
|
|
}, nullopt); |
|
|
|
cpytor((char*)&value, data); |
|
|
|
cmptor = +[](const void* lhs, const void* rhs) { |
|
|
|
return *reinterpret_cast<const U*>(lhs) == *reinterpret_cast<const U*>(rhs); |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
static_assert(list_contains_class<int, int>::value, "list_contains_class doesn't work properly"); |
|
|
@ -84,6 +91,9 @@ namespace gp{ |
|
|
|
new(dest) actual(gp::move(*(actual*)src)); |
|
|
|
}, nullopt); |
|
|
|
mvtor((char*)&value, data); |
|
|
|
cmptor = +[](const void* lhs, const void* rhs) { |
|
|
|
return *reinterpret_cast<const U*>(lhs) == *reinterpret_cast<const U*>(rhs); |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
fixed_variant(const fixed_variant& oth) |
|
|
@ -91,6 +101,7 @@ namespace gp{ |
|
|
|
, dtor{oth.dtor} |
|
|
|
, cpytor{oth.cpytor} |
|
|
|
, mvtor{oth.mvtor} |
|
|
|
, cmptor{oth.cmptor} |
|
|
|
{ |
|
|
|
cpytor((char*)oth.data, (char*)data); |
|
|
|
} |
|
|
@ -100,6 +111,7 @@ namespace gp{ |
|
|
|
, dtor{oth.dtor} |
|
|
|
, cpytor{oth.cpytor} |
|
|
|
, mvtor{oth.mvtor} |
|
|
|
, cmptor{oth.cmptor} |
|
|
|
{ |
|
|
|
cpytor(oth.data, data); |
|
|
|
} |
|
|
@ -109,6 +121,7 @@ namespace gp{ |
|
|
|
, dtor{oth.dtor} |
|
|
|
, cpytor{oth.cpytor} |
|
|
|
, mvtor{oth.mvtor} |
|
|
|
, cmptor{oth.cmptor} |
|
|
|
{ |
|
|
|
oth.index = std::numeric_limits<std::size_t>::max(); |
|
|
|
mvtor(oth.data, data); |
|
|
@ -147,6 +160,7 @@ namespace gp{ |
|
|
|
dtor = value.dtor; |
|
|
|
mvtor = value.mvtor; |
|
|
|
cpytor(value.data, data); |
|
|
|
cmptor = value.cmptor; |
|
|
|
} |
|
|
|
|
|
|
|
void operator=(fixed_variant&& value) |
|
|
@ -161,6 +175,7 @@ namespace gp{ |
|
|
|
index = value.index; |
|
|
|
value.index = std::numeric_limits<std::size_t>::max(); |
|
|
|
mvtor(value.data, data); |
|
|
|
cmptor = value.cmptor; |
|
|
|
} |
|
|
|
|
|
|
|
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type> |
|
|
@ -175,6 +190,9 @@ namespace gp{ |
|
|
|
dtor = gp::function([](void* thing){((U*)thing)->~U();}, nullopt); |
|
|
|
cpytor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(*(U*)src);}, nullopt); |
|
|
|
mvtor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));}, nullopt); |
|
|
|
cmptor = +[](const void* lhs, const void* rhs) { |
|
|
|
return *reinterpret_cast<const U*>(lhs) == *reinterpret_cast<const U*>(rhs); |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
template<typename U, typename std::enable_if<list_contains_class<U,T...>::value,int>::type> |
|
|
@ -189,6 +207,9 @@ namespace gp{ |
|
|
|
dtor = gp::function([](void* thing){((U*)thing)->~U();}, nullopt); |
|
|
|
cpytor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(*(U*)src);}, nullopt); |
|
|
|
mvtor = gp::function<void(void*, void*)>([](void* src, void* dest){new(dest) U(gp::move(*(U*)src));}, nullopt); |
|
|
|
cmptor = +[](const void* lhs, const void* rhs) { |
|
|
|
return *reinterpret_cast<const U*>(lhs) == *reinterpret_cast<const U*>(rhs); |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
~fixed_variant() |
|
|
@ -199,7 +220,7 @@ namespace gp{ |
|
|
|
index = std::numeric_limits<std::size_t>::max(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Brutally decay the variant into the given type. |
|
|
|
Will throw (@see bad_variant_access) if exceptions are enabled, else behaviour is undefined. |
|
|
@ -219,6 +240,26 @@ namespace gp{ |
|
|
|
} |
|
|
|
return *reinterpret_cast<U*>(data); |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Brutally decay the variant into the given type. |
|
|
|
Will throw (@see bad_variant_access) if exceptions are enabled, else behaviour is undefined. |
|
|
|
* |
|
|
|
* @tparam U the type to decay towards |
|
|
|
* @return constexpr U& a decayed reference to the variant |
|
|
|
*/ |
|
|
|
template<typename U> |
|
|
|
constexpr const U& value() const |
|
|
|
{ |
|
|
|
if constexpr (gp_config::has_exceptions) |
|
|
|
{ |
|
|
|
if(r_index_of<gp::remove_cvref_t<U>, T...>::value != index) |
|
|
|
{ |
|
|
|
throw bad_variant_access<U>{}; |
|
|
|
} |
|
|
|
} |
|
|
|
return *reinterpret_cast<const U*>(data); |
|
|
|
} |
|
|
|
|
|
|
|
/**
|
|
|
|
* @brief Tests if the variant is of a particular type. |
|
|
@ -228,7 +269,7 @@ namespace gp{ |
|
|
|
* @return false if the types don't match |
|
|
|
*/ |
|
|
|
template<typename U> |
|
|
|
constexpr bool is_a() |
|
|
|
constexpr bool is_a() const |
|
|
|
{ |
|
|
|
if(r_index_of<gp::remove_cvref_t<U>, T...>::value == index) |
|
|
|
{ |
|
|
@ -239,5 +280,13 @@ namespace gp{ |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
bool operator==(const fixed_variant& rhs) const { |
|
|
|
if(index != rhs.index) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
// TODO: find a way to remove those const casts, the underlying things also use const so it is safe but kind ew
|
|
|
|
return cmptor(reinterpret_cast<const void*>(const_cast<const fixed_variant*const>(this)), reinterpret_cast<const void*>(const_cast<const fixed_variant*const>(&rhs))); |
|
|
|
} |
|
|
|
}; |
|
|
|
} |