value_ptr.hpp 2.8 KB

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