BAN: Variant with reference now supports copy/assign

This commit is contained in:
Bananymous 2023-04-18 20:21:23 +03:00
parent 6aeac17072
commit 5aaf2128a8
1 changed files with 34 additions and 10 deletions

View File

@ -4,6 +4,8 @@
#include <BAN/Math.h> #include <BAN/Math.h>
#include <BAN/Move.h> #include <BAN/Move.h>
#include <string.h>
namespace BAN namespace BAN
{ {
@ -53,7 +55,10 @@ namespace BAN
void move_construct(size_t index, uint8_t* source, uint8_t* target) void move_construct(size_t index, uint8_t* source, uint8_t* target)
{ {
if (index == 0) if (index == 0)
if constexpr(!is_lvalue_reference_v<T>)
new (target) T(move(*reinterpret_cast<T*>(source))); new (target) T(move(*reinterpret_cast<T*>(source)));
else
memcpy(target, source, sizeof(remove_reference_t<T>*));
else if constexpr(sizeof...(Ts) > 0) else if constexpr(sizeof...(Ts) > 0)
move_construct<Ts...>(index - 1, source, target); move_construct<Ts...>(index - 1, source, target);
else else
@ -64,7 +69,10 @@ namespace BAN
void copy_construct(size_t index, const uint8_t* source, uint8_t* target) void copy_construct(size_t index, const uint8_t* source, uint8_t* target)
{ {
if (index == 0) if (index == 0)
if constexpr(!is_lvalue_reference_v<T>)
new (target) T(*reinterpret_cast<const T*>(source)); new (target) T(*reinterpret_cast<const T*>(source));
else
memcpy(target, source, sizeof(remove_reference_t<T>*));
else if constexpr(sizeof...(Ts) > 0) else if constexpr(sizeof...(Ts) > 0)
copy_construct<Ts...>(index - 1, source, target); copy_construct<Ts...>(index - 1, source, target);
else else
@ -75,7 +83,10 @@ namespace BAN
void move_assign(size_t index, uint8_t* source, uint8_t* target) void move_assign(size_t index, uint8_t* source, uint8_t* target)
{ {
if (index == 0) if (index == 0)
if constexpr(!is_lvalue_reference_v<T>)
*reinterpret_cast<T*>(target) = move(*reinterpret_cast<T*>(source)); *reinterpret_cast<T*>(target) = move(*reinterpret_cast<T*>(source));
else
memcpy(target, source, sizeof(remove_reference_t<T>*));
else if constexpr(sizeof...(Ts) > 0) else if constexpr(sizeof...(Ts) > 0)
move_assign<Ts...>(index - 1, source, target); move_assign<Ts...>(index - 1, source, target);
else else
@ -86,7 +97,10 @@ namespace BAN
void copy_assign(size_t index, const uint8_t* source, uint8_t* target) void copy_assign(size_t index, const uint8_t* source, uint8_t* target)
{ {
if (index == 0) if (index == 0)
if constexpr(!is_lvalue_reference_v<T>)
*reinterpret_cast<T*>(target) = *reinterpret_cast<const T*>(source); *reinterpret_cast<T*>(target) = *reinterpret_cast<const T*>(source);
else
memcpy(target, source, sizeof(remove_reference_t<T>*));
else if constexpr(sizeof...(Ts) > 0) else if constexpr(sizeof...(Ts) > 0)
copy_assign<Ts...>(index - 1, source, target); copy_assign<Ts...>(index - 1, source, target);
else else
@ -142,9 +156,7 @@ namespace BAN
Variant& operator=(Variant&& other) Variant& operator=(Variant&& other)
{ {
if (m_index == other.m_index) if (m_index == other.m_index)
{
detail::move_assign<Ts...>(m_index, other.m_storage, m_storage); detail::move_assign<Ts...>(m_index, other.m_storage, m_storage);
}
else else
{ {
clear(); clear();
@ -158,9 +170,7 @@ namespace BAN
Variant& operator=(const Variant& other) Variant& operator=(const Variant& other)
{ {
if (m_index == other.m_index) if (m_index == other.m_index)
{
detail::copy_assign<Ts...>(m_index, other.m_storage, m_storage); detail::copy_assign<Ts...>(m_index, other.m_storage, m_storage);
}
else else
{ {
clear(); clear();
@ -173,14 +183,28 @@ namespace BAN
template<typename T> template<typename T>
Variant& operator=(T&& value) requires (can_have<T>() && !is_lvalue_reference_v<T>) Variant& operator=(T&& value) requires (can_have<T>() && !is_lvalue_reference_v<T>)
{ {
*this = Variant(move(value)); if (size_t index = detail::index<T, Ts...>(); index == m_index)
get<T>() = move(value);
else
{
clear();
new (m_storage) T(move(value));
m_index = index;
}
return *this; return *this;
} }
template<typename T> template<typename T>
Variant& operator=(const T& value) requires (can_have<T>() && !is_lvalue_reference_v<T>) Variant& operator=(const T& value) requires (can_have<T>() && !is_lvalue_reference_v<T>)
{ {
*this = Variant(value); if (size_t index = detail::index<T, Ts...>(); index == m_index)
get<T>() = value;
else
{
clear();
new (m_storage) T(value);
m_index = index;
}
return *this; return *this;
} }