value_ptr.hpp 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  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>
  13. using clone_func = T* (T::*)() const;
  14. template <typename T, typename = void>
  15. class value_ptr_copy;
  16. template <typename T>
  17. struct value_ptr_copy<T, typename std::enable_if<!std::is_polymorphic<T>::value>::type> {
  18. T * Copy( T * ptr ) const { return ptr ? new T(*ptr) : nullptr; }
  19. };
  20. #define POLYMORPHIC_VALUE_PTR_GROUP_FROM_CLONE_FUNCTION( fclone ) \
  21. template <typename T> \
  22. struct value_ptr_copy<T, typename std::enable_if<std::is_polymorphic<T>::value \
  23. && std::is_same<clone_func<T>, decltype(&T::fclone)>::value>::type> { \
  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:
  34. using element_type = T;
  35. using pointer = element_type *;
  36. using reference = element_type &;
  37. value_ptr() noexcept : _ptr(nullptr) {}
  38. value_ptr(T * const & p) = delete;
  39. value_ptr(T * && p) noexcept(std::is_nothrow_move_constructible<T>::value) : _ptr(std::move(p)) {}
  40. value_ptr(value_ptr const & other) : _ptr(detail::value_ptr_copy<T>::Copy(other._ptr)) {}
  41. value_ptr(value_ptr && other) noexcept(noexcept(std::swap(_ptr, other._ptr))) : _ptr(nullptr) { std::swap(_ptr, other._ptr); }
  42. static value_ptr copy_of(T * const & p) {
  43. return detail::value_ptr_copy<T>().Copy(p);
  44. }
  45. template <typename Y>
  46. explicit operator value_ptr<Y>() const {
  47. return Copy(_ptr);
  48. }
  49. ~value_ptr() { delete _ptr; }
  50. value_ptr & operator=(value_ptr const & other) noexcept(noexcept(swap(_ptr, other._ptr))) {
  51. swap(_ptr, value_ptr{other}._ptr);
  52. return *this;
  53. }
  54. value_ptr & operator=(value_ptr && other) noexcept(noexcept(swap(_ptr, other._ptr))) {
  55. swap(_ptr, other._ptr);
  56. return *this;
  57. }
  58. operator bool() const noexcept {
  59. return static_cast<bool>(_ptr);
  60. }
  61. pointer get() const noexcept { return _ptr; }
  62. pointer operator->() const noexcept { return get(); }
  63. reference operator*() const noexcept { return *get(); }
  64. private:
  65. T * _ptr;
  66. };
  67. POINTER_TEMPLATE_COMPARE( value_ptr )