value_ptr.hpp 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. //
  2. // copy_ptr.hpp
  3. // pointers
  4. //
  5. // Created by Sam Jaffe on 12/6/16.
  6. //
  7. #pragma once
  8. #include <memory>
  9. #include "detail/compare.hpp"
  10. #include "pointer_fwd.hpp"
  11. namespace pointers {
  12. namespace detail {
  13. template <typename T> using clone_func = T * (T::*)() const;
  14. template <typename T, typename = void> class value_ptr_copy;
  15. template <typename T>
  16. struct value_ptr_copy<T, std::enable_if_t<!std::is_polymorphic<T>::value>> {
  17. T * Copy(T * ptr) const { return ptr ? new T(*ptr) : nullptr; }
  18. };
  19. #define POLYMORPHIC_VALUE_PTR_GROUP_FROM_CLONE_FUNCTION(fclone) \
  20. template <typename T> \
  21. struct value_ptr_copy< \
  22. T, std::enable_if_t< \
  23. std::is_polymorphic<T>::value && \
  24. std::is_same<clone_func<T>, decltype(&T::fclone)>::value>> { \
  25. T * Copy(T * ptr) const { return ptr ? ptr->fclone() : nullptr; } \
  26. }
  27. POLYMORPHIC_VALUE_PTR_GROUP_FROM_CLONE_FUNCTION(Clone);
  28. POLYMORPHIC_VALUE_PTR_GROUP_FROM_CLONE_FUNCTION(clone);
  29. POLYMORPHIC_VALUE_PTR_GROUP_FROM_CLONE_FUNCTION(Copy);
  30. POLYMORPHIC_VALUE_PTR_GROUP_FROM_CLONE_FUNCTION(copy);
  31. }
  32. template <typename T>
  33. class value_ptr : private detail::value_ptr_copy<T>,
  34. public detail::pointer_compare<value_ptr<T>> {
  35. public:
  36. using element_type = T;
  37. using pointer = element_type *;
  38. using reference = element_type &;
  39. value_ptr() noexcept : _ptr(nullptr) {}
  40. value_ptr(T * const & p) = delete;
  41. value_ptr(T *&& p) noexcept(std::is_nothrow_move_constructible<T>::value)
  42. : _ptr(std::move(p)) {}
  43. value_ptr(value_ptr const & other)
  44. : _ptr(detail::value_ptr_copy<T>::Copy(other._ptr)) {}
  45. value_ptr(value_ptr && other) noexcept(noexcept(std::swap(_ptr,
  46. other._ptr)))
  47. : _ptr(nullptr) {
  48. std::swap(_ptr, other._ptr);
  49. }
  50. static value_ptr copy_of(T * const & p) {
  51. return detail::value_ptr_copy<T>().Copy(p);
  52. }
  53. template <typename Y> explicit operator value_ptr<Y>() const {
  54. return Copy(_ptr);
  55. }
  56. ~value_ptr() { delete _ptr; }
  57. value_ptr & operator=(value_ptr const & other) {
  58. swap(_ptr, value_ptr{other}._ptr);
  59. return *this;
  60. }
  61. value_ptr & operator=(value_ptr && other) noexcept {
  62. swap(_ptr, other._ptr);
  63. return *this;
  64. }
  65. operator bool() const noexcept { return static_cast<bool>(_ptr); }
  66. pointer get() const noexcept { return _ptr; }
  67. pointer operator->() const noexcept { return get(); }
  68. reference operator*() const noexcept { return *get(); }
  69. private:
  70. static void swap(T * a, T * b) {
  71. T * tmp = a;
  72. a = b;
  73. b = tmp;
  74. }
  75. T * _ptr;
  76. };
  77. template <typename T, typename... Args>
  78. value_ptr<T> make_value(Args &&... args) {
  79. return value_ptr<T>(new T(std::forward<Args>(args)...));
  80. }
  81. }