ifd_pointer.hpp 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. #pragma once
  2. namespace stream { namespace detail {
  3. class ifd_pointer {
  4. private:
  5. void * (*copy)(void *){nullptr};
  6. void (*destroy)(void *){nullptr};
  7. void * ptr{nullptr};
  8. public:
  9. template <typename T>
  10. ifd_pointer(T && value)
  11. : copy(&ifd_pointer::copy_<T>), destroy(&ifd_pointer::destroy_<T>),
  12. ptr(copy(&value)) {}
  13. ifd_pointer() = default;
  14. ifd_pointer(ifd_pointer const & other)
  15. : copy(other.copy), destroy(other.destroy),
  16. ptr(copy ? copy(other.ptr) : nullptr) {}
  17. ifd_pointer(ifd_pointer && other) {
  18. *this = std::forward<ifd_pointer>(other);
  19. }
  20. ifd_pointer & operator=(ifd_pointer const & other) {
  21. return *this = ifd_pointer(other);
  22. }
  23. ~ifd_pointer() {
  24. if (destroy) destroy(ptr);
  25. }
  26. ifd_pointer & operator=(ifd_pointer && other) {
  27. swap(*this, other);
  28. return *this;
  29. }
  30. void * get() const { return ptr; }
  31. operator bool() const { return ptr; }
  32. friend bool operator==(ifd_pointer const & lhs, ifd_pointer const & rhs) {
  33. return lhs.ptr == rhs.ptr;
  34. }
  35. private:
  36. friend void swap(ifd_pointer & lhs, ifd_pointer & rhs) {
  37. using ::std::swap;
  38. swap(lhs.copy, rhs.copy);
  39. swap(lhs.destroy, rhs.destroy);
  40. swap(lhs.ptr, rhs.ptr);
  41. }
  42. template <typename T> static void * copy_(void * p) {
  43. return (void *)new T(*(T *)(p));
  44. }
  45. template <typename T> static void destroy_(void * p) { delete (T *)(p); }
  46. };
  47. }}