Sfoglia il codice sorgente

Wrap things in the pointers namespace.

Sam Jaffe 5 anni fa
parent
commit
1d5c880869

+ 66 - 59
include/pointers/const_propogating_ptr.hpp

@@ -12,71 +12,78 @@
 #include "detail/get_ptr.hpp"
 #include "pointer_fwd.hpp"
 
-template <typename P>
-class const_propogating_ptr
-    : private detail::get_ptr<P>,
-      public detail::pointer_compare<const_propogating_ptr<P>> {
-public:
-  using element_type = typename std::pointer_traits<P>::element_type;
-  using pointer = element_type *;
-  using reference = element_type &;
-  using const_pointer = element_type const *;
-  using const_reference = element_type const &;
+namespace pointers {
 
-  const_propogating_ptr() noexcept : _ptr() {}
-  const_propogating_ptr(P const & p) noexcept(
-      std::is_nothrow_copy_constructible<P>::value)
-      : _ptr(p) {}
-  const_propogating_ptr(P && p) noexcept(
-      std::is_nothrow_move_constructible<P>::value)
-      : _ptr(std::move(p)) {}
-  template <typename Y, typename = typename std::enable_if<
-                            std::is_constructible<P, Y>::value>::type>
-  const_propogating_ptr(Y const & p) : _ptr(p) {}
-  template <typename Y, typename = typename std::enable_if<
-                            std::is_constructible<P, Y>::value>::type>
-  const_propogating_ptr(Y && p) : _ptr(std::forward<Y>(p)) {}
+  template <typename P>
+  class const_propogating_ptr
+      : private detail::get_ptr<P>,
+        public detail::pointer_compare<const_propogating_ptr<P>> {
+  public:
+    using element_type = typename std::pointer_traits<P>::element_type;
+    using pointer = element_type *;
+    using reference = element_type &;
+    using const_pointer = element_type const *;
+    using const_reference = element_type const &;
 
-  const_propogating_ptr(const_propogating_ptr &) noexcept(
-      std::is_nothrow_copy_constructible<P>::value) = default;
-  const_propogating_ptr(const_propogating_ptr &&) noexcept(
-      std::is_nothrow_move_constructible<P>::value) = default;
-  const_propogating_ptr(const_propogating_ptr const &) = delete;
-  const_propogating_ptr & operator=(const_propogating_ptr &) noexcept(
-      std::is_nothrow_copy_assignable<P>::value) = default;
-  const_propogating_ptr & operator=(const_propogating_ptr &&) noexcept(
-      std::is_nothrow_move_assignable<P>::value) = default;
-  const_propogating_ptr & operator=(const_propogating_ptr const &) = delete;
+    const_propogating_ptr() noexcept : _ptr() {}
+    const_propogating_ptr(P const & p) noexcept(
+        std::is_nothrow_copy_constructible<P>::value)
+        : _ptr(p) {}
+    const_propogating_ptr(P && p) noexcept(
+        std::is_nothrow_move_constructible<P>::value)
+        : _ptr(std::move(p)) {}
+    template <typename Y, typename = typename std::enable_if<
+                              std::is_constructible<P, Y>::value>::type>
+    const_propogating_ptr(Y const & p) : _ptr(p) {}
+    template <typename Y, typename = typename std::enable_if<
+                              std::is_constructible<P, Y>::value>::type>
+    const_propogating_ptr(Y && p) : _ptr(std::forward<Y>(p)) {}
 
-  template <typename Y>
-      explicit operator const_propogating_ptr<Y>() &
-      noexcept(std::is_nothrow_constructible<P, Y>::value) {
-    return _ptr;
-  }
+    const_propogating_ptr(const_propogating_ptr &) noexcept(
+        std::is_nothrow_copy_constructible<P>::value) = default;
+    const_propogating_ptr(const_propogating_ptr &&) noexcept(
+        std::is_nothrow_move_constructible<P>::value) = default;
+    const_propogating_ptr(const_propogating_ptr const &) = delete;
+    const_propogating_ptr & operator=(const_propogating_ptr &) noexcept(
+        std::is_nothrow_copy_assignable<P>::value) = default;
+    const_propogating_ptr & operator=(const_propogating_ptr &&) noexcept(
+        std::is_nothrow_move_assignable<P>::value) = default;
+    const_propogating_ptr & operator=(const_propogating_ptr const &) = delete;
 
-  template <typename Y>
-  explicit operator const_ptr<Y>() const
-      noexcept(std::is_nothrow_constructible<P, Y>::value) {
-    return _ptr;
-  }
+    template <typename Y>
+        explicit operator const_propogating_ptr<Y>() &
+        noexcept(std::is_nothrow_constructible<P, Y>::value) {
+      return _ptr;
+    }
 
-  template <typename Y>
-  explicit operator const_propogating_ptr<Y>() const & = delete;
+    template <typename Y>
+    explicit operator const_ptr<Y>() const
+        noexcept(std::is_nothrow_constructible<P, Y>::value) {
+      return _ptr;
+    }
 
-  operator bool() const noexcept { return static_cast<bool>(_ptr); }
+    template <typename Y>
+    explicit operator const_propogating_ptr<Y>() const & = delete;
 
-  reference operator*() noexcept(noexcept(*_ptr)) { return *_ptr; }
-  pointer get() noexcept(noexcept(detail::get_ptr<P>::get(_ptr))) {
-    return detail::get_ptr<P>::get(_ptr);
-  }
-  pointer operator->() noexcept(noexcept(get())) { return get(); }
+    operator bool() const noexcept { return static_cast<bool>(_ptr); }
 
-  const_reference operator*() const noexcept(noexcept(*_ptr)) { return *_ptr; }
-  const_pointer get() const noexcept(noexcept(detail::get_ptr<P>::get(_ptr))) {
-    return detail::get_ptr<P>::get(_ptr);
-  }
-  const_pointer operator->() const noexcept(noexcept(get())) { return get(); }
+    reference operator*() noexcept(noexcept(*_ptr)) { return *_ptr; }
+    pointer get() noexcept(noexcept(detail::get_ptr<P>::get(_ptr))) {
+      return detail::get_ptr<P>::get(_ptr);
+    }
+    pointer operator->() noexcept(noexcept(get())) { return get(); }
 
-private:
-  P _ptr;
-};
+    const_reference operator*() const noexcept(noexcept(*_ptr)) {
+      return *_ptr;
+    }
+    const_pointer get() const
+        noexcept(noexcept(detail::get_ptr<P>::get(_ptr))) {
+      return detail::get_ptr<P>::get(_ptr);
+    }
+    const_pointer operator->() const noexcept(noexcept(get())) { return get(); }
+
+  private:
+    P _ptr;
+  };
+
+}

+ 42 - 37
include/pointers/const_ptr.hpp

@@ -12,40 +12,45 @@
 #include "detail/get_ptr.hpp"
 #include "pointer_fwd.hpp"
 
-template <typename P>
-class const_ptr : private detail::get_ptr<P>,
-                  public detail::pointer_compare<const_ptr<P>> {
-public:
-  using element_type = typename std::pointer_traits<P>::element_type;
-  using pointer = element_type const *;
-  using reference = element_type const &;
-
-  const_ptr() noexcept : _ptr(nullptr) {}
-  const_ptr(P const & p) noexcept(std::is_nothrow_copy_constructible<P>::value)
-      : _ptr(p) {}
-  const_ptr(P && p) noexcept(std::is_nothrow_move_constructible<P>::value)
-      : _ptr(std::move(p)) {}
-  template <typename Y, typename = typename std::enable_if<
-                            std::is_constructible<P, Y>::value>::type>
-  const_ptr(Y const & p) : _ptr(p) {}
-  template <typename Y, typename = typename std::enable_if<
-                            std::is_constructible<P, Y>::value>::type>
-  const_ptr(Y && p) : _ptr(std::forward<Y>(p)) {}
-
-  template <typename Y>
-  explicit operator const_ptr<Y>() const
-      noexcept(std::is_nothrow_constructible<P, Y>::value) {
-    return _ptr;
-  }
-
-  operator bool() const noexcept { return static_cast<bool>(_ptr); }
-
-  reference operator*() const noexcept(noexcept(*_ptr)) { return *_ptr; }
-  pointer get() const noexcept(noexcept(detail::get_ptr<P>::get(_ptr))) {
-    return detail::get_ptr<P>::get(_ptr);
-  }
-  pointer operator->() const noexcept(noexcept(get())) { return get(); }
-
-private:
-  P _ptr;
-};
+namespace pointers {
+
+  template <typename P>
+  class const_ptr : private detail::get_ptr<P>,
+                    public detail::pointer_compare<const_ptr<P>> {
+  public:
+    using element_type = typename std::pointer_traits<P>::element_type;
+    using pointer = element_type const *;
+    using reference = element_type const &;
+
+    const_ptr() noexcept : _ptr(nullptr) {}
+    const_ptr(P const & p) noexcept(
+        std::is_nothrow_copy_constructible<P>::value)
+        : _ptr(p) {}
+    const_ptr(P && p) noexcept(std::is_nothrow_move_constructible<P>::value)
+        : _ptr(std::move(p)) {}
+    template <typename Y, typename = typename std::enable_if<
+                              std::is_constructible<P, Y>::value>::type>
+    const_ptr(Y const & p) : _ptr(p) {}
+    template <typename Y, typename = typename std::enable_if<
+                              std::is_constructible<P, Y>::value>::type>
+    const_ptr(Y && p) : _ptr(std::forward<Y>(p)) {}
+
+    template <typename Y>
+    explicit operator const_ptr<Y>() const
+        noexcept(std::is_nothrow_constructible<P, Y>::value) {
+      return _ptr;
+    }
+
+    operator bool() const noexcept { return static_cast<bool>(_ptr); }
+
+    reference operator*() const noexcept(noexcept(*_ptr)) { return *_ptr; }
+    pointer get() const noexcept(noexcept(detail::get_ptr<P>::get(_ptr))) {
+      return detail::get_ptr<P>::get(_ptr);
+    }
+    pointer operator->() const noexcept(noexcept(get())) { return get(); }
+
+  private:
+    P _ptr;
+  };
+
+}

+ 2 - 2
include/pointers/detail/compare.hpp

@@ -7,7 +7,7 @@
 
 #pragma once
 
-namespace detail {
+namespace pointers { namespace detail {
   template <typename Self> struct pointer_compare {
     friend bool operator==(Self const & lhs, Self const & rhs) {
       return lhs.get() == rhs.get();
@@ -56,4 +56,4 @@ namespace detail {
       return !(nullptr < rhs);
     }
   };
-}
+}}

+ 4 - 2
include/pointers/detail/get_ptr.hpp

@@ -1,6 +1,7 @@
 #pragma once
 
-namespace detail {
+namespace pointers { namespace detail {
+
   template <typename P, typename = void> struct get_ptr {
     decltype(std::declval<P>().get()) get(P const & ptr) const {
       return std::addressof(*ptr);
@@ -22,4 +23,5 @@ namespace detail {
       return ptr.get();
     }
   };
-}
+
+}}

+ 10 - 6
include/pointers/exception.hpp

@@ -4,10 +4,14 @@
 
 #include "pointer_fwd.hpp"
 
-class unchecked_pointer_exception : public std::logic_error {
-  using std::logic_error::logic_error;
-};
+namespace pointers {
 
-class null_pointer_exception : public std::invalid_argument {
-  using std::invalid_argument::invalid_argument;
-};
+  class unchecked_pointer_exception : public std::logic_error {
+    using std::logic_error::logic_error;
+  };
+
+  class null_pointer_exception : public std::invalid_argument {
+    using std::invalid_argument::invalid_argument;
+  };
+
+}

+ 64 - 60
include/pointers/maybe_null.hpp

@@ -15,82 +15,86 @@
 #include "exception.hpp"
 #include "pointer_fwd.hpp"
 
-template <typename P> class maybe_null<not_null<P>>; // not permitted
-
 #if defined(DEBUG)
 #define set_tested(value) tested_ = value
 #else
 #define set_tested(_)
 #endif
 
-template <typename P>
-class maybe_null : private detail::get_ptr<P>,
-                   public detail::pointer_compare<maybe_null<P>> {
-public:
-  using element_type = typename std::pointer_traits<P>::element_type;
-  using pointer = element_type *;
-  using reference = element_type &;
+namespace pointers {
+
+  template <typename P> class maybe_null<not_null<P>>; // not permitted
 
-  maybe_null() noexcept : _ptr(nullptr) {}
-  maybe_null(P const & p) noexcept(std::is_nothrow_copy_constructible<P>::value)
-      : _ptr(p) {}
-  maybe_null(P && p) noexcept(std::is_nothrow_move_constructible<P>::value)
-      : _ptr(std::move(p)) {}
-  template <typename Y, typename = typename std::enable_if<
-                            std::is_constructible<P, Y>::value>::type>
-  maybe_null(Y const & p) : _ptr(p) {}
-  template <typename Y, typename = typename std::enable_if<
-                            std::is_constructible<P, Y>::value>::type>
-  maybe_null(Y && p) : _ptr(std::forward<Y>(p)) {}
-  maybe_null(maybe_null const &) noexcept(
-      std::is_nothrow_copy_constructible<P>::value) = default;
-  maybe_null(maybe_null &&) noexcept(
-      std::is_nothrow_move_constructible<P>::value) = default;
-  template <typename Y>
-  maybe_null(maybe_null<Y> const & other) noexcept(
-      std::is_nothrow_constructible<P, Y>::value)
-      : _ptr(other._ptr) {
-    set_tested(other.tested_);
-  }
+  template <typename P>
+  class maybe_null : private detail::get_ptr<P>,
+                     public detail::pointer_compare<maybe_null<P>> {
+  public:
+    using element_type = typename std::pointer_traits<P>::element_type;
+    using pointer = element_type *;
+    using reference = element_type &;
 
-  maybe_null & operator=(maybe_null const &) noexcept(
-      std::is_nothrow_copy_assignable<P>::value) = default;
-  maybe_null & operator=(maybe_null &&) noexcept(
-      std::is_nothrow_move_assignable<P>::value) = default;
+    maybe_null() noexcept : _ptr(nullptr) {}
+    maybe_null(P const & p) noexcept(
+        std::is_nothrow_copy_constructible<P>::value)
+        : _ptr(p) {}
+    maybe_null(P && p) noexcept(std::is_nothrow_move_constructible<P>::value)
+        : _ptr(std::move(p)) {}
+    template <typename Y, typename = typename std::enable_if<
+                              std::is_constructible<P, Y>::value>::type>
+    maybe_null(Y const & p) : _ptr(p) {}
+    template <typename Y, typename = typename std::enable_if<
+                              std::is_constructible<P, Y>::value>::type>
+    maybe_null(Y && p) : _ptr(std::forward<Y>(p)) {}
+    maybe_null(maybe_null const &) noexcept(
+        std::is_nothrow_copy_constructible<P>::value) = default;
+    maybe_null(maybe_null &&) noexcept(
+        std::is_nothrow_move_constructible<P>::value) = default;
+    template <typename Y>
+    maybe_null(maybe_null<Y> const & other) noexcept(
+        std::is_nothrow_constructible<P, Y>::value)
+        : _ptr(other._ptr) {
+      set_tested(other.tested_);
+    }
 
-  operator bool() const noexcept {
-    set_tested(true);
-    return static_cast<bool>(_ptr);
-  }
+    maybe_null & operator=(maybe_null const &) noexcept(
+        std::is_nothrow_copy_assignable<P>::value) = default;
+    maybe_null & operator=(maybe_null &&) noexcept(
+        std::is_nothrow_move_assignable<P>::value) = default;
 
-  pointer get() const noexcept(noexcept(detail::get_ptr<P>::get(_ptr))) {
-    return detail::get_ptr<P>::get(_ptr);
-  }
-  pointer operator->() const /*throw(unchecked_pointer_exception)*/ {
-    return std::addressof(operator*());
-  }
-  reference operator*() const /*throw(unchecked_pointer_exception)*/ {
-#if defined(DEBUG)
-    if (!tested_) {
-      throw unchecked_pointer_exception{
-          "did not verify that pointer was non-null"};
+    operator bool() const noexcept {
+      set_tested(true);
+      return static_cast<bool>(_ptr);
     }
+
+    pointer get() const noexcept(noexcept(detail::get_ptr<P>::get(_ptr))) {
+      return detail::get_ptr<P>::get(_ptr);
+    }
+    pointer operator->() const /*throw(unchecked_pointer_exception)*/ {
+      return std::addressof(operator*());
+    }
+    reference operator*() const /*throw(unchecked_pointer_exception)*/ {
+#if defined(DEBUG)
+      if (!tested_) {
+        throw unchecked_pointer_exception{
+            "did not verify that pointer was non-null"};
+      }
 #endif
-    if (!_ptr) {
-      throw null_pointer_exception{"dereferencing maybe_null in null state"};
+      if (!_ptr) {
+        throw null_pointer_exception{"dereferencing maybe_null in null state"};
+      }
+      return *_ptr;
     }
-    return *_ptr;
-  }
 
-  void reset(P const & p) { operator=(maybe_null(p)); }
-  void reset(P && p = P()) { operator=(maybe_null(std::move(p))); }
+    void reset(P const & p) { operator=(maybe_null(p)); }
+    void reset(P && p = P()) { operator=(maybe_null(std::move(p))); }
 
-private:
-  template <typename Y> friend class maybe_null;
-  P _ptr;
+  private:
+    template <typename Y> friend class maybe_null;
+    P _ptr;
 #if defined(DEBUG)
-  mutable bool tested_ = false;
+    mutable bool tested_ = false;
 #endif
-};
+  };
 
+}
 #undef set_tested

+ 55 - 51
include/pointers/not_null.hpp

@@ -15,63 +15,67 @@
 #include "maybe_null.hpp"
 #include "pointer_fwd.hpp"
 
-template <typename P>
-class not_null<std::weak_ptr<P>>; // A weak_ptr cannot be a not_null
+namespace pointers {
 
-template <typename P>
-class not_null : public detail::pointer_compare<not_null<P>> {
-public:
-  using element_type = typename std::pointer_traits<P>::element_type;
-  using pointer = element_type *;
-  using reference = element_type &;
+  template <typename P>
+  class not_null<std::weak_ptr<P>>; // A weak_ptr cannot be a not_null
 
-  explicit not_null(std::nullptr_t) = delete;
-  explicit not_null(int) = delete;
-  not_null(P const & p) : _ptr(p) { validate(); }
-  not_null(P && p) : _ptr(std::move(p)) { validate(); }
-  template <typename Y, typename = typename std::enable_if<
-                            std::is_constructible<P, Y>::value>::type>
-  not_null(Y const & p) : _ptr(p) {
-    validate();
-  }
-  template <typename Y, typename = typename std::enable_if<
-                            std::is_constructible<P, Y>::value>::type>
-  not_null(Y && p) : _ptr(std::forward<Y>(p)) {
-    validate();
-  }
-  not_null(not_null const &) noexcept(
-      std::is_nothrow_copy_constructible<P>::value) = default;
-  not_null(not_null &&) = delete;
+  template <typename P>
+  class not_null : public detail::pointer_compare<not_null<P>> {
+  public:
+    using element_type = typename std::pointer_traits<P>::element_type;
+    using pointer = element_type *;
+    using reference = element_type &;
 
-  template <typename Y>
-  explicit operator maybe_null<Y>() const
-      noexcept(std::is_nothrow_constructible<Y, P>::value) {
-    return _ptr;
-  }
-  template <typename Y>
-  explicit operator not_null<Y>() const
-      noexcept(std::is_nothrow_constructible<Y, P>::value) {
-    return _ptr;
-  }
+    explicit not_null(std::nullptr_t) = delete;
+    explicit not_null(int) = delete;
+    not_null(P const & p) : _ptr(p) { validate(); }
+    not_null(P && p) : _ptr(std::move(p)) { validate(); }
+    template <typename Y, typename = typename std::enable_if<
+                              std::is_constructible<P, Y>::value>::type>
+    not_null(Y const & p) : _ptr(p) {
+      validate();
+    }
+    template <typename Y, typename = typename std::enable_if<
+                              std::is_constructible<P, Y>::value>::type>
+    not_null(Y && p) : _ptr(std::forward<Y>(p)) {
+      validate();
+    }
+    not_null(not_null const &) noexcept(
+        std::is_nothrow_copy_constructible<P>::value) = default;
+    not_null(not_null &&) = delete;
+
+    template <typename Y>
+    explicit operator maybe_null<Y>() const
+        noexcept(std::is_nothrow_constructible<Y, P>::value) {
+      return _ptr;
+    }
+    template <typename Y>
+    explicit operator not_null<Y>() const
+        noexcept(std::is_nothrow_constructible<Y, P>::value) {
+      return _ptr;
+    }
 
-  not_null & operator=(not_null const &) noexcept(
-      std::is_nothrow_copy_assignable<P>::value) = default;
-  not_null & operator=(not_null &&) = delete;
+    not_null & operator=(not_null const &) noexcept(
+        std::is_nothrow_copy_assignable<P>::value) = default;
+    not_null & operator=(not_null &&) = delete;
 
-  operator bool() const noexcept { return true; }
+    operator bool() const noexcept { return true; }
 
-  pointer get() const noexcept { return detail::get_ptr<P>().get(_ptr); }
-  reference operator*() const noexcept { return *_ptr; }
-  pointer operator->() const noexcept { return get(); }
+    pointer get() const noexcept { return detail::get_ptr<P>().get(_ptr); }
+    reference operator*() const noexcept { return *_ptr; }
+    pointer operator->() const noexcept { return get(); }
 
-  void reset(P const & p) { operator=(not_null(p)); }
-  void reset(P && p) { operator=(not_null(std::forward(p))); }
+    void reset(P const & p) { operator=(not_null(p)); }
+    void reset(P && p) { operator=(not_null(std::forward(p))); }
 
-private:
-  void validate() {
-    if (get() == nullptr) {
-      throw null_pointer_exception{"not_null<P> cannot be null"};
+  private:
+    void validate() {
+      if (get() == nullptr) {
+        throw null_pointer_exception{"not_null<P> cannot be null"};
+      }
     }
-  }
-  P _ptr;
-};
+    P _ptr;
+  };
+
+}

+ 11 - 7
include/pointers/pointer_fwd.hpp

@@ -7,11 +7,15 @@
 
 #pragma once
 
-template <typename> class const_propogating_ptr;
-template <typename> class const_ptr;
-template <typename> class maybe_null;
-template <typename> class not_null;
-template <typename> class owner;
+namespace pointers {
 
-class null_pointer_exception;
-class unchecked_pointer_exception;
+  template <typename> class const_propogating_ptr;
+  template <typename> class const_ptr;
+  template <typename> class maybe_null;
+  template <typename> class not_null;
+  template <typename> class owner;
+
+  class null_pointer_exception;
+  class unchecked_pointer_exception;
+
+}

+ 67 - 63
include/pointers/value_ptr.hpp

@@ -12,15 +12,16 @@
 #include "detail/compare.hpp"
 #include "pointer_fwd.hpp"
 
-namespace detail {
-  template <typename T> using clone_func = T * (T::*)() const;
+namespace pointers {
+  namespace detail {
+    template <typename T> using clone_func = T * (T::*)() const;
 
-  template <typename T, typename = void> class value_ptr_copy;
+    template <typename T, typename = void> class value_ptr_copy;
 
-  template <typename T>
-  struct value_ptr_copy<T, std::enable_if_t<!std::is_polymorphic<T>::value>> {
-    T * Copy(T * ptr) const { return ptr ? new T(*ptr) : nullptr; }
-  };
+    template <typename T>
+    struct value_ptr_copy<T, std::enable_if_t<!std::is_polymorphic<T>::value>> {
+      T * Copy(T * ptr) const { return ptr ? new T(*ptr) : nullptr; }
+    };
 
 #define POLYMORPHIC_VALUE_PTR_GROUP_FROM_CLONE_FUNCTION(fclone)                \
   template <typename T>                                                        \
@@ -31,65 +32,68 @@ namespace detail {
     T * Copy(T * ptr) const { return ptr ? ptr->fclone() : nullptr; }          \
   }
 
-  POLYMORPHIC_VALUE_PTR_GROUP_FROM_CLONE_FUNCTION(Clone);
-  POLYMORPHIC_VALUE_PTR_GROUP_FROM_CLONE_FUNCTION(clone);
-  POLYMORPHIC_VALUE_PTR_GROUP_FROM_CLONE_FUNCTION(Copy);
-  POLYMORPHIC_VALUE_PTR_GROUP_FROM_CLONE_FUNCTION(copy);
-}
-
-template <typename T>
-class value_ptr : private detail::value_ptr_copy<T>,
-                  public detail::pointer_compare<value_ptr<T>> {
-public:
-  using element_type = T;
-  using pointer = element_type *;
-  using reference = element_type &;
-
-  value_ptr() noexcept : _ptr(nullptr) {}
-  value_ptr(T * const & p) = delete;
-  value_ptr(T *&& p) noexcept(std::is_nothrow_move_constructible<T>::value)
-      : _ptr(std::move(p)) {}
-  value_ptr(value_ptr const & other)
-      : _ptr(detail::value_ptr_copy<T>::Copy(other._ptr)) {}
-  value_ptr(value_ptr && other) noexcept(noexcept(std::swap(_ptr, other._ptr)))
-      : _ptr(nullptr) {
-    std::swap(_ptr, other._ptr);
-  }
-  static value_ptr copy_of(T * const & p) {
-    return detail::value_ptr_copy<T>().Copy(p);
-  }
-
-  template <typename Y> explicit operator value_ptr<Y>() const {
-    return Copy(_ptr);
+    POLYMORPHIC_VALUE_PTR_GROUP_FROM_CLONE_FUNCTION(Clone);
+    POLYMORPHIC_VALUE_PTR_GROUP_FROM_CLONE_FUNCTION(clone);
+    POLYMORPHIC_VALUE_PTR_GROUP_FROM_CLONE_FUNCTION(Copy);
+    POLYMORPHIC_VALUE_PTR_GROUP_FROM_CLONE_FUNCTION(copy);
   }
 
-  ~value_ptr() { delete _ptr; }
-
-  value_ptr & operator=(value_ptr const & other) {
-    swap(_ptr, value_ptr{other}._ptr);
-    return *this;
-  }
-  value_ptr & operator=(value_ptr && other) noexcept {
-    swap(_ptr, other._ptr);
-    return *this;
-  }
-
-  operator bool() const noexcept { return static_cast<bool>(_ptr); }
-
-  pointer get() const noexcept { return _ptr; }
-  pointer operator->() const noexcept { return get(); }
-  reference operator*() const noexcept { return *get(); }
+  template <typename T>
+  class value_ptr : private detail::value_ptr_copy<T>,
+                    public detail::pointer_compare<value_ptr<T>> {
+  public:
+    using element_type = T;
+    using pointer = element_type *;
+    using reference = element_type &;
+
+    value_ptr() noexcept : _ptr(nullptr) {}
+    value_ptr(T * const & p) = delete;
+    value_ptr(T *&& p) noexcept(std::is_nothrow_move_constructible<T>::value)
+        : _ptr(std::move(p)) {}
+    value_ptr(value_ptr const & other)
+        : _ptr(detail::value_ptr_copy<T>::Copy(other._ptr)) {}
+    value_ptr(value_ptr && other) noexcept(noexcept(std::swap(_ptr,
+                                                              other._ptr)))
+        : _ptr(nullptr) {
+      std::swap(_ptr, other._ptr);
+    }
+    static value_ptr copy_of(T * const & p) {
+      return detail::value_ptr_copy<T>().Copy(p);
+    }
+
+    template <typename Y> explicit operator value_ptr<Y>() const {
+      return Copy(_ptr);
+    }
+
+    ~value_ptr() { delete _ptr; }
+
+    value_ptr & operator=(value_ptr const & other) {
+      swap(_ptr, value_ptr{other}._ptr);
+      return *this;
+    }
+    value_ptr & operator=(value_ptr && other) noexcept {
+      swap(_ptr, other._ptr);
+      return *this;
+    }
+
+    operator bool() const noexcept { return static_cast<bool>(_ptr); }
+
+    pointer get() const noexcept { return _ptr; }
+    pointer operator->() const noexcept { return get(); }
+    reference operator*() const noexcept { return *get(); }
+
+  private:
+    static void swap(T * a, T * b) {
+      T * tmp = a;
+      a = b;
+      b = tmp;
+    }
+    T * _ptr;
+  };
 
-private:
-  static void swap(T * a, T * b) {
-    T * tmp = a;
-    a = b;
-    b = tmp;
+  template <typename T, typename... Args>
+  value_ptr<T> make_value(Args &&... args) {
+    return value_ptr<T>(new T(std::forward<Args>(args)...));
   }
-  T * _ptr;
-};
 
-template <typename T, typename... Args>
-value_ptr<T> make_value(Args &&... args) {
-  return value_ptr<T>(new T(std::forward<Args>(args)...));
 }

+ 2 - 0
test/const_propogating_ptr_test.cxx

@@ -13,6 +13,8 @@
 
 #include "test_stubs.h"
 
+using namespace pointers;
+
 TEST(ConstPropogatingPtrTest, NonConstCPPCallsNonConstMethods) {
   std::shared_ptr<const_tracking_stub> p{new const_tracking_stub};
   const_propogating_ptr<std::shared_ptr<const_tracking_stub>> cp{p};

+ 2 - 0
test/const_ptr_test.cxx

@@ -12,6 +12,8 @@
 
 #include "test_stubs.h"
 
+using namespace pointers;
+
 TEST(ConstPtrTest, NonConstCPCallConstMethods) {
   std::shared_ptr<const_tracking_stub> p{new const_tracking_stub};
   const_ptr<std::shared_ptr<const_tracking_stub>> cp{p};

+ 2 - 0
test/maybe_null_test.cxx

@@ -18,6 +18,8 @@
 
 #include "test_stubs.h"
 
+using namespace pointers;
+
 TEST(MaybeNullPtrTest, NullPtrEvaluatesAsFalse) {
   maybe_null<std::shared_ptr<int>> mn{nullptr};
   EXPECT_FALSE(mn);

+ 2 - 0
test/not_null_test.cxx

@@ -11,6 +11,8 @@
 
 #include "test_stubs.h"
 
+using namespace pointers;
+
 TEST(NonNullPtrTest, ThrowsIfNullptrIsSnuckIn) {
   EXPECT_THROW(not_null<std::shared_ptr<int>>(std::shared_ptr<int>(nullptr)),
                null_pointer_exception);

+ 4 - 2
test/value_ptr_test.cxx

@@ -16,7 +16,7 @@
 struct copy_me {};
 struct copy_me_throw {};
 
-namespace detail {
+namespace pointers { namespace detail {
   template <> class value_ptr_copy<copy_me_throw> {
   protected:
     copy_me_throw * Copy(copy_me_throw const * p) const {
@@ -24,7 +24,7 @@ namespace detail {
       return new copy_me_throw{*p};
     }
   };
-}
+}}
 
 class base {
 public:
@@ -47,6 +47,8 @@ public:
   virtual int id() const override { return ID; }
 };
 
+using namespace pointers;
+
 TEST(ValuePtrTest, CanCopySimpleObject) {
   value_ptr<copy_me> c1{new copy_me};
   value_ptr<copy_me> c2{c1};