#pragma once namespace stream { namespace detail { class ifd_pointer { private: void * (*copy)(void *){nullptr}; void (*destroy)(void *){nullptr}; void * ptr{nullptr}; public: template ifd_pointer(T && value) : copy(&ifd_pointer::copy_), destroy(&ifd_pointer::destroy_), ptr(copy(&value)) {} ifd_pointer() = default; ifd_pointer(ifd_pointer const & other) : copy(other.copy), destroy(other.destroy), ptr(copy(other.ptr)) {} ifd_pointer(ifd_pointer && other) { *this = std::forward(other); } ifd_pointer & operator=(ifd_pointer const & other) { return *this = ifd_pointer(other); } ~ifd_pointer() { if (destroy) destroy(ptr); } ifd_pointer & operator=(ifd_pointer && other) { swap(*this, other); return *this; } void * get() const { return ptr; } private: friend void swap(ifd_pointer & lhs, ifd_pointer & rhs) { using ::std::swap; swap(lhs.copy, rhs.copy); swap(lhs.destroy, rhs.destroy); swap(lhs.ptr, rhs.ptr); } template static void * copy_(void * p) { return (void *)new T(*(T *)(p)); } template static void destroy_(void * p) { delete (T *)(p); } }; }}