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>
  32. class value_ptr : private detail::value_ptr_copy<T>,
  33. public detail::pointer_compare<value_ptr<T>> {
  34. public:
  35. using element_type = T;
  36. using pointer = element_type *;
  37. using reference = element_type &;
  38. value_ptr() noexcept : _ptr(nullptr) {}
  39. value_ptr(T * const & p) = delete;
  40. value_ptr(T *&& p) noexcept(detail::is_nt_mc<T>::value)
  41. : _ptr(std::move(p)) {}
  42. value_ptr(value_ptr const & other)
  43. : _ptr(detail::value_ptr_copy<T>::Copy(other._ptr)) {}
  44. value_ptr(value_ptr && other) noexcept(noexcept(std::swap(_ptr, other._ptr)))
  45. : _ptr(nullptr) {
  46. std::swap(_ptr, other._ptr);
  47. }
  48. static value_ptr copy_of(T * const & p) {
  49. return detail::value_ptr_copy<T>().Copy(p);
  50. }
  51. template <typename Y> explicit operator value_ptr<Y>() const {
  52. return Copy(_ptr);
  53. }
  54. ~value_ptr() { delete _ptr; }
  55. value_ptr & operator=(value_ptr const & other) {
  56. swap(_ptr, value_ptr{other}._ptr);
  57. return *this;
  58. }
  59. value_ptr & operator=(value_ptr && other) noexcept {
  60. swap(_ptr, other._ptr);
  61. return *this;
  62. }
  63. operator bool() const noexcept { return static_cast<bool>(_ptr); }
  64. pointer get() const noexcept { return _ptr; }
  65. pointer operator->() const noexcept { return get(); }
  66. reference operator*() const noexcept { return *get(); }
  67. private:
  68. static void swap(T * a, T * b) {
  69. T * tmp = a;
  70. a = b;
  71. b = tmp;
  72. }
  73. T * _ptr;
  74. };
  75. template <typename T, typename... Args>
  76. value_ptr<T> make_value(Args &&... args) {
  77. return value_ptr<T>(new T(std::forward<Args>(args)...));
  78. }