Remove polymorphic_storage helper

This commit is contained in:
Nikita Lisitsa 2020-11-22 12:07:14 +03:00
parent a1cf646633
commit cb468aa675

View file

@ -1,155 +0,0 @@
#pragma once
#include <type_traits>
#include <algorithm>
namespace psemek::util
{
template <typename I, std::size_t Size = sizeof(I)>
struct polymorhpic_storage
{
static constexpr std::size_t align = std::max(alignof(I*), alignof(I));
static constexpr std::size_t size = std::max(sizeof(I*), std::max(sizeof(I), Size));
polymorhpic_storage() noexcept = default;
polymorhpic_storage(polymorhpic_storage && other) noexcept;
polymorhpic_storage & operator = (polymorhpic_storage && other) noexcept;
polymorhpic_storage(polymorhpic_storage const &) = delete;
polymorhpic_storage & operator = (polymorhpic_storage const &) = delete;
template <typename T, typename ... Args>
void emplace(Args && ... args);
I * get() const noexcept;
void reset() noexcept;
~polymorhpic_storage() noexcept
{
reset();
}
explicit operator bool() const
{
return static_cast<bool>(manager_);
}
private:
std::aligned_storage_t<size, align> storage_;
using manager = void*(*)(void *, void *, int);
manager manager_ = nullptr;
static constexpr int op_get = 1;
static constexpr int op_move = 2;
static constexpr int op_destroy = 3;
};
template <typename I, std::size_t Size>
polymorhpic_storage<I, Size>::polymorhpic_storage(polymorhpic_storage && other) noexcept
{
manager_ = other.manager_;
if (manager_)
{
manager_(&other.storage_, &storage_, op_move);
}
other.reset();
}
template <typename I, std::size_t Size>
polymorhpic_storage<I, Size> & polymorhpic_storage<I, Size>::operator = (polymorhpic_storage && other) noexcept
{
if (this == &other)
return *this;
reset();
manager_ = other.manager_;
if (manager_)
{
manager_(&other.storage_, &storage_, op_move);
}
other.reset();
return *this;
}
template <typename I, std::size_t Size>
template <typename T, typename ... Args>
void polymorhpic_storage<I, Size>::emplace(Args && ... args)
{
constexpr bool static_storage = true
&& (sizeof(T) <= size)
&& (alignof(T) <= align)
&& ((align % alignof(T)) == 0)
&& std::is_nothrow_move_constructible_v<T>
;
reset();
if constexpr (static_storage)
{
static_assert(sizeof(T) <= size);
new (reinterpret_cast<T *>(&storage_)) T(std::forward<Args>(args)...);
manager_ = [](void * src, void * dst, int op) -> void*
{
switch (op)
{
case op_get:
return src;
case op_move:
new (reinterpret_cast<T *>(dst)) T(std::move(*reinterpret_cast<T *>(src)));
break;
case op_destroy:
reinterpret_cast<T *>(src)->~T();
break;
default:
break;
}
return nullptr;
};
}
else
{
*reinterpret_cast<T**>(&storage_) = new T(std::forward<Args>(args)...);
manager_ = [](void * src, void * dst, int op) -> void*
{
switch (op)
{
case op_get:
return *reinterpret_cast<T**>(src);
case op_move:
*reinterpret_cast<T**>(dst) = *reinterpret_cast<T**>(src);
*reinterpret_cast<T**>(src) = nullptr;
break;
case op_destroy:
delete *reinterpret_cast<T**>(src);
break;
default:
break;
}
return nullptr;
};
}
}
template <typename I, std::size_t Size>
I * polymorhpic_storage<I, Size>::get() const noexcept
{
if (!manager_) return nullptr;
return static_cast<I *>(manager_(const_cast<void *>(static_cast<void const *>(&storage_)), nullptr, op_get));
}
template <typename I, std::size_t Size>
void polymorhpic_storage<I, Size>::reset() noexcept
{
if (!manager_) return;
manager_(&storage_, nullptr, op_destroy);
manager_ = nullptr;
}
}