Ver Fonte

Merge branch 'cleanup'

* cleanup:
  Wrap things in the pointers namespace.
  Move exceptions to their own file.
  Stop compressing noexcept declarations...
  Move get_ptr helpers to detail folder.
  Move ptr_compare.hpp to the detail folder.
  Stop using macros to define pointer comparators.
Sam Jaffe há 5 anos atrás
pai
commit
87139ba616

+ 67 - 56
include/pointers/const_propogating_ptr.hpp

@@ -8,71 +8,82 @@
 #pragma once
 #include <memory>
 
+#include "detail/compare.hpp"
+#include "detail/get_ptr.hpp"
 #include "pointer_fwd.hpp"
-#include "ptr_compare.hpp"
 
-template <typename P> class const_propogating_ptr : private detail::get_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(detail::is_nt_cc<P>::value)
-      : _ptr(p) {}
-  const_propogating_ptr(P && p) noexcept(detail::is_nt_mc<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(
-      detail::is_nt_cc<P>::value) = default;
-  const_propogating_ptr(const_propogating_ptr &&) noexcept(
-      detail::is_nt_mc<P>::value) = default;
-  const_propogating_ptr(const_propogating_ptr const &) = delete;
-  const_propogating_ptr & operator=(const_propogating_ptr &) noexcept(
-      detail::is_nt_ca<P>::value) = default;
-  const_propogating_ptr & operator=(const_propogating_ptr &&) noexcept(
-      detail::is_nt_ma<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(detail::is_nt_c<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(detail::is_nt_c<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(); }
 
-POINTER_TEMPLATE_COMPARE(const_propogating_ptr)
+  private:
+    P _ptr;
+  };
+
+}

+ 45 - 37
include/pointers/const_ptr.hpp

@@ -8,41 +8,49 @@
 #pragma once
 #include <memory>
 
+#include "detail/compare.hpp"
+#include "detail/get_ptr.hpp"
 #include "pointer_fwd.hpp"
-#include "ptr_compare.hpp"
-
-template <typename P> class const_ptr : private detail::get_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(detail::is_nt_cc<P>::value) : _ptr(p) {}
-  const_ptr(P && p) noexcept(detail::is_nt_mc<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(detail::is_nt_c<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;
-};
-
-POINTER_TEMPLATE_COMPARE(const_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;
+  };
+
+}

+ 59 - 0
include/pointers/detail/compare.hpp

@@ -0,0 +1,59 @@
+//
+//  ptr_compare.hpp
+//  pointers
+//
+//  Created by Sam Jaffe on 1/5/17.
+//
+
+#pragma once
+
+namespace pointers { namespace detail {
+  template <typename Self> struct pointer_compare {
+    friend bool operator==(Self const & lhs, Self const & rhs) {
+      return lhs.get() == rhs.get();
+    }
+    friend bool operator<(Self const & lhs, Self const & rhs) {
+      return lhs.get() < rhs.get();
+    }
+    friend bool operator!=(Self const & lhs, Self const & rhs) {
+      return !(lhs == rhs);
+    }
+    friend bool operator>(Self const & lhs, Self const & rhs) {
+      return rhs < lhs;
+    }
+    friend bool operator<=(Self const & lhs, Self const & rhs) {
+      return !(rhs < lhs);
+    }
+    friend bool operator>=(Self const & lhs, Self const & rhs) {
+      return !(lhs < rhs);
+    }
+    friend bool operator==(Self const & lhs, std::nullptr_t) { return !lhs; }
+    friend bool operator<(Self const & lhs, std::nullptr_t) {
+      return lhs.get() < nullptr;
+    }
+    friend bool operator!=(Self const & lhs, std::nullptr_t) { return !!lhs; }
+    friend bool operator>(Self const & lhs, std::nullptr_t) {
+      return nullptr < lhs;
+    }
+    friend bool operator<=(Self const & lhs, std::nullptr_t) {
+      return !(nullptr < lhs);
+    }
+    friend bool operator>=(Self const & lhs, std::nullptr_t) {
+      return !(lhs < nullptr);
+    }
+    friend bool operator==(std::nullptr_t, Self const & rhs) { return !rhs; }
+    friend bool operator<(std::nullptr_t, Self const & rhs) {
+      return nullptr < rhs.get();
+    }
+    friend bool operator!=(std::nullptr_t, Self const & rhs) { return !!rhs; }
+    friend bool operator>(std::nullptr_t, Self const & rhs) {
+      return rhs < nullptr;
+    }
+    friend bool operator<=(std::nullptr_t, Self const & rhs) {
+      return !(rhs < nullptr);
+    }
+    friend bool operator>=(std::nullptr_t, Self const & rhs) {
+      return !(nullptr < rhs);
+    }
+  };
+}}

+ 27 - 0
include/pointers/detail/get_ptr.hpp

@@ -0,0 +1,27 @@
+#pragma once
+
+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);
+    }
+  };
+
+  template <typename T> struct get_ptr<std::weak_ptr<T>> {
+    void get(std::weak_ptr<T> const & ptr) throw();
+  };
+
+  template <typename T> struct get_ptr<T *> {
+    T * get(T * ptr) const { return ptr; }
+  };
+
+  template <typename P>
+  struct get_ptr<P, typename std::enable_if<!std::is_void<decltype(
+                        std::declval<P>().get())>::value>::type> {
+    decltype(std::declval<P>().get()) get(P const & ptr) const {
+      return ptr.get();
+    }
+  };
+
+}}

+ 17 - 0
include/pointers/exception.hpp

@@ -0,0 +1,17 @@
+#pragma once
+
+#include <stdexcept>
+
+#include "pointer_fwd.hpp"
+
+namespace pointers {
+
+  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;
+  };
+
+}

+ 67 - 60
include/pointers/maybe_null.hpp

@@ -10,14 +10,10 @@
 
 #include <memory>
 
+#include "detail/compare.hpp"
+#include "detail/get_ptr.hpp"
+#include "exception.hpp"
 #include "pointer_fwd.hpp"
-#include "ptr_compare.hpp"
-
-class unchecked_pointer_exception : public std::logic_error {
-  using std::logic_error::logic_error;
-};
-
-template <typename P> class maybe_null<not_null<P>>; // not permitted
 
 #if defined(DEBUG)
 #define set_tested(value) tested_ = value
@@ -25,69 +21,80 @@ template <typename P> class maybe_null<not_null<P>>; // not permitted
 #define set_tested(_)
 #endif
 
-template <typename P> class maybe_null : private detail::get_ptr<P> {
-public:
-  using element_type = typename std::pointer_traits<P>::element_type;
-  using pointer = element_type *;
-  using reference = element_type &;
+namespace pointers {
 
-  maybe_null() noexcept : _ptr(nullptr) {}
-  maybe_null(P const & p) noexcept(detail::is_nt_cc<P>::value) : _ptr(p) {}
-  maybe_null(P && p) noexcept(detail::is_nt_mc<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(detail::is_nt_cc<P>::value) = default;
-  maybe_null(maybe_null &&) noexcept(detail::is_nt_mc<P>::value) = default;
-  template <typename Y>
-  maybe_null(maybe_null<Y> const & other) noexcept(detail::is_nt_c<P, Y>::value)
-      : _ptr(other._ptr) {
-    set_tested(other.tested_);
-  }
+  template <typename P> class maybe_null<not_null<P>>; // not permitted
 
-  maybe_null &
-  operator=(maybe_null const &) noexcept(detail::is_nt_ca<P>::value) = default;
-  maybe_null &
-  operator=(maybe_null &&) noexcept(detail::is_nt_ma<P>::value) = default;
+  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 &;
 
-  operator bool() const noexcept {
-    set_tested(true);
-    return static_cast<bool>(_ptr);
-  }
+    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_);
+    }
 
-  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"};
+    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;
+
+    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
-POINTER_TEMPLATE_COMPARE(maybe_null)

+ 56 - 50
include/pointers/not_null.hpp

@@ -10,66 +10,72 @@
 
 #include <memory>
 
+#include "detail/compare.hpp"
+#include "exception.hpp"
 #include "maybe_null.hpp"
 #include "pointer_fwd.hpp"
-#include "ptr_compare.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:
-  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(detail::is_nt_cc<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(detail::is_nt_c<Y, P>::value) {
-    return _ptr;
-  }
-  template <typename Y>
-  explicit operator not_null<Y>() const noexcept(detail::is_nt_c<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(detail::is_nt_ca<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;
+  };
 
-POINTER_TEMPLATE_COMPARE(not_null)
+}

+ 8 - 42
include/pointers/pointer_fwd.hpp

@@ -7,49 +7,15 @@
 
 #pragma once
 
-#include <stdexcept>
+namespace pointers {
 
-template <typename> class not_null;
-template <typename> class maybe_null;
-template <typename> class owner;
-template <typename> class const_propogating_ptr;
-template <typename> class const_ptr;
+  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 unchecked_pointer_exception;
+  class null_pointer_exception;
+  class unchecked_pointer_exception;
 
-class null_pointer_exception : public std::invalid_argument {
-  using std::invalid_argument::invalid_argument;
-};
-
-namespace detail {
-  template <typename P> using is_nt_cc = std::is_nothrow_copy_constructible<P>;
-  template <typename P> using is_nt_ca = std::is_nothrow_copy_assignable<P>;
-  template <typename P> using is_nt_mc = std::is_nothrow_move_constructible<P>;
-  template <typename P> using is_nt_ma = std::is_nothrow_move_assignable<P>;
-  template <typename P, typename Y>
-  using is_nt_c = std::is_nothrow_constructible<P, Y>;
-  template <typename P, typename Y>
-  using is_nt_a = std::is_nothrow_assignable<P, Y>;
-
-  template <typename P, typename = void> struct get_ptr {
-    decltype(std::declval<P>().get()) get(P const & ptr) const {
-      return std::addressof(*ptr);
-    }
-  };
-
-  template <typename T> struct get_ptr<std::weak_ptr<T>> {
-    void get(std::weak_ptr<T> const & ptr) throw();
-  };
-
-  template <typename T> struct get_ptr<T *> {
-    T * get(T * ptr) const { return ptr; }
-  };
-
-  template <typename P>
-  struct get_ptr<P, typename std::enable_if<!std::is_void<decltype(
-                        std::declval<P>().get())>::value>::type> {
-    decltype(std::declval<P>().get()) get(P const & ptr) const {
-      return ptr.get();
-    }
-  };
 }

+ 0 - 115
include/pointers/ptr_compare.hpp

@@ -1,115 +0,0 @@
-//
-//  ptr_compare.hpp
-//  pointers
-//
-//  Created by Sam Jaffe on 1/5/17.
-//
-
-#pragma once
-
-#define POINTER_TEMPLATE_COMPARE(ptr_t)                                        \
-  POINTER_TEMPLATE_COMPARE_FULL(ptr_t, (typename T), (T), (typename U), (U))
-
-#define EXPAND(...) __VA_ARGS__
-
-#define POINTER_TEMPLATE_COMPARE_FULL(ptr_t, T_tname, T, U_tname, U)           \
-  template <EXPAND T_tname, EXPAND U_tname>                                    \
-  bool operator==(ptr_t<EXPAND T> const & lhs,                                 \
-                  ptr_t<EXPAND U> const & rhs) noexcept {                      \
-    return lhs.get() == rhs.get();                                             \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname, EXPAND U_tname>                                    \
-  bool operator!=(ptr_t<EXPAND T> const & lhs,                                 \
-                  ptr_t<EXPAND U> const & rhs) noexcept {                      \
-    return !(lhs == rhs);                                                      \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname, EXPAND U_tname>                                    \
-  bool operator<(ptr_t<EXPAND T> const & lhs,                                  \
-                 ptr_t<EXPAND U> const & rhs) noexcept {                       \
-    typedef                                                                    \
-        typename std::common_type<typename ptr_t<EXPAND T>::pointer,           \
-                                  typename ptr_t<EXPAND U>::pointer>::type V;  \
-    return std::less<V>(lhs.get(), rhs.get());                                 \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname, EXPAND U_tname>                                    \
-  bool operator>(ptr_t<EXPAND T> const & lhs,                                  \
-                 ptr_t<EXPAND U> const & rhs) noexcept {                       \
-    return rhs < lhs;                                                          \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname, EXPAND U_tname>                                    \
-  bool operator<=(ptr_t<EXPAND T> const & lhs,                                 \
-                  ptr_t<EXPAND U> const & rhs) noexcept {                      \
-    return !(rhs < lhs);                                                       \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname, EXPAND U_tname>                                    \
-  bool operator>=(ptr_t<EXPAND T> const & lhs,                                 \
-                  ptr_t<EXPAND U> const & rhs) noexcept {                      \
-    return !(lhs < rhs);                                                       \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname>                                                    \
-  bool operator==(ptr_t<EXPAND T> const & lhs, std::nullptr_t) noexcept {      \
-    return !lhs;                                                               \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname>                                                    \
-  bool operator==(std::nullptr_t, ptr_t<EXPAND T> const & rhs) noexcept {      \
-    return !rhs;                                                               \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname>                                                    \
-  bool operator!=(ptr_t<EXPAND T> const & lhs, std::nullptr_t) noexcept {      \
-    return static_cast<bool>(lhs);                                             \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname>                                                    \
-  bool operator!=(std::nullptr_t, ptr_t<EXPAND T> const & rhs) noexcept {      \
-    return static_cast<bool>(rhs);                                             \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname>                                                    \
-  bool operator<(ptr_t<EXPAND T> const & lhs, std::nullptr_t) noexcept {       \
-    typedef typename ptr_t<EXPAND T>::pointer V;                               \
-    return std::less<V>(lhs.get(), nullptr);                                   \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname>                                                    \
-  bool operator<(std::nullptr_t, ptr_t<EXPAND T> const & rhs) noexcept {       \
-    typedef typename ptr_t<EXPAND T>::pointer V;                               \
-    return std::less<V>(nullptr, rhs.get());                                   \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname>                                                    \
-  bool operator>(ptr_t<EXPAND T> const & lhs, std::nullptr_t) noexcept {       \
-    return nullptr < lhs;                                                      \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname>                                                    \
-  bool operator>(std::nullptr_t, ptr_t<EXPAND T> const & rhs) noexcept {       \
-    return rhs < nullptr;                                                      \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname>                                                    \
-  bool operator<=(ptr_t<EXPAND T> const & lhs, std::nullptr_t) noexcept {      \
-    return !(nullptr < lhs);                                                   \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname>                                                    \
-  bool operator<=(std::nullptr_t, ptr_t<EXPAND T> const & rhs) noexcept {      \
-    return !(rhs < nullptr);                                                   \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname>                                                    \
-  bool operator>=(ptr_t<EXPAND T> const & lhs, std::nullptr_t) noexcept {      \
-    return !(lhs < nullptr);                                                   \
-  }                                                                            \
-                                                                               \
-  template <EXPAND T_tname>                                                    \
-  bool operator>=(std::nullptr_t, ptr_t<EXPAND T> const & rhs) noexcept {      \
-    return !(nullptr < rhs);                                                   \
-  }

+ 68 - 64
include/pointers/value_ptr.hpp

@@ -9,18 +9,19 @@
 
 #include <memory>
 
+#include "detail/compare.hpp"
 #include "pointer_fwd.hpp"
-#include "ptr_compare.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:
-  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(detail::is_nt_mc<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)...));
 }
-
-POINTER_TEMPLATE_COMPARE(value_ptr)

+ 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};