#include namespace sprawl { namespace memory { template class OpaquePtr; template struct CreateAs{}; } } template class sprawl::memory::OpaquePtr { public: class Deleter { public: virtual void Delete(void*) = 0; }; template class TypeDeleter : public Deleter { public: virtual void Delete(void* ptr) { reinterpret_cast(ptr)->~T(); } }; template OpaquePtr(CreateAs const&, Params&&... params) : m_ptr() , m_deleter() // Same size since no members, direct reinterpret cast should be fine. { static_assert(sizeof(T) == size, "Opaque pointer delcared with size that does not match the type used to construct it."); new(m_ptr) T(std::forward(params)...); new(m_deleter) TypeDeleter(); } ~OpaquePtr() { reinterpret_cast(m_deleter)->Delete(m_ptr); } template T& As() { static_assert(sizeof(T) == size, "Opaque pointer delcared with size that does not match the type used to access it."); return *reinterpret_cast(m_ptr); } template T const& As() const { static_assert(sizeof(T) == size, "Opaque pointer delcared with size that does not match the type used to access it."); return *reinterpret_cast(m_ptr); } template operator T&() { static_assert(sizeof(T) == size, "Opaque pointer delcared with size that does not match the type used to access it."); return *reinterpret_cast(m_ptr); } template operator T const&() const { static_assert(sizeof(T) == size, "Opaque pointer delcared with size that does not match the type used to access it."); return *reinterpret_cast(m_ptr); } private: unsigned char m_ptr[size]; unsigned char m_deleter[sizeof(Deleter)]; };