Browse Source

Adding new pointer types.
const_propogating_ptr - if it's const, then it dereferences to a 'T const &' no matter what.
const_ptr - it's always const under there
copy_ptr - for when you want unique_ptr-style ownership, but the owning object might need to be copied.

Samuel Jaffe 9 years ago
parent
commit
e8869d2823
4 changed files with 343 additions and 0 deletions
  1. 155 0
      const_propogating_ptr.hpp
  2. 34 0
      const_ptr.hpp
  3. 152 0
      copy_ptr.hpp
  4. 2 0
      pointer_fwd.hpp

+ 155 - 0
const_propogating_ptr.hpp

@@ -0,0 +1,155 @@
+//
+//  const_propogating_ptr.hpp
+//  pointers
+//
+//  Created by Sam Jaffe on 12/3/16.
+//
+
+#pragma once
+#include <memory>
+
+#include "pointer_fwd.hpp"
+
+template <typename T>
+class const_propogating_ptr {
+public:
+  using element_type = typename std::pointer_traits<T>::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() : _ptr(nullptr) {}
+  const_propogating_ptr(T const & p) : _ptr(p) {}
+  const_propogating_ptr(T && p) : _ptr(std::move(p)) {}
+  
+  const_propogating_ptr(const_propogating_ptr & other) : _ptr(other._ptr) {}
+  const_propogating_ptr(const_propogating_ptr &&) = default;
+  const_propogating_ptr(const_propogating_ptr const &) = delete;
+  const_propogating_ptr& operator=(const_propogating_ptr & other) { _ptr = other._ptr; return *this; }
+  const_propogating_ptr& operator=(const_propogating_ptr &&) = default;
+  const_propogating_ptr& operator=(const_propogating_ptr const &) = delete;
+  
+  template <typename Y>
+  explicit operator const_propogating_ptr<Y>() & {
+    return _ptr;
+  }
+  
+  template <typename Y>
+  explicit operator const_ptr<Y>() const {
+    return _ptr;
+  }
+  
+  template <typename Y>
+  explicit operator const_propogating_ptr<Y>() const & = delete;
+  
+  operator bool() const {
+    return bool(_ptr);
+  }
+  
+  reference operator*() { return *_ptr; }
+  pointer get() { return std::addressof(operator*()); }
+  pointer operator->() { return get(); }
+  
+  const_reference operator*() const { return *_ptr; }
+  const_pointer get() const { return std::addressof(operator*()); }
+  const_pointer operator->() const { return get(); }
+  
+private:
+  T _ptr;
+};
+
+template <typename T, typename U>
+bool operator==(const_propogating_ptr<T> const&lhs, const_propogating_ptr<U> const&rhs) {
+  return lhs.get() == rhs.get();
+}
+
+template <typename T, typename U>
+bool operator!=(const_propogating_ptr<T> const&lhs, const_propogating_ptr<U> const&rhs) {
+  return !(lhs == rhs);
+}
+
+template <typename T, typename U>
+bool operator< (const_propogating_ptr<T> const&lhs, const_propogating_ptr<U> const&rhs) {
+  typedef typename std::common_type<
+  typename const_propogating_ptr<T>::pointer,
+  typename const_propogating_ptr<U>::pointer>::type V;
+  return std::less<V>(lhs.get(), rhs.get());
+}
+
+template <typename T, typename U>
+bool operator> (const_propogating_ptr<T> const&lhs, const_propogating_ptr<U> const&rhs) {
+  return rhs < lhs;
+}
+
+template <typename T, typename U>
+bool operator<=(const_propogating_ptr<T> const&lhs, const_propogating_ptr<U> const&rhs) {
+  return !(rhs < lhs);
+}
+
+template <typename T, typename U>
+bool operator>=(const_propogating_ptr<T> const&lhs, const_propogating_ptr<U> const&rhs) {
+  return !(lhs < rhs);
+}
+
+template <typename T>
+bool operator==(const_propogating_ptr<T> const&lhs, std::nullptr_t) {
+  return !lhs;
+}
+
+template <typename T>
+bool operator==(std::nullptr_t, const_propogating_ptr<T> const&rhs) {
+  return !rhs;
+}
+
+template <typename T>
+bool operator!=(const_propogating_ptr<T> const&lhs, std::nullptr_t) {
+  return static_cast<bool>(lhs);
+}
+
+template <typename T>
+bool operator!=(std::nullptr_t, const_propogating_ptr<T> const&rhs) {
+  return static_cast<bool>(rhs);
+}
+
+template <typename T>
+bool operator< (const_propogating_ptr<T> const&lhs, std::nullptr_t) {
+  typedef typename const_propogating_ptr<T>::pointer V;
+  return std::less<V>(lhs.get(), nullptr);
+}
+
+template <typename T>
+bool operator< (std::nullptr_t, const_propogating_ptr<T> const&rhs) {
+  typedef typename const_propogating_ptr<T>::pointer V;
+  return std::less<V>(nullptr, rhs.get());
+}
+
+template <typename T>
+bool operator> (const_propogating_ptr<T> const&lhs, std::nullptr_t) {
+  return nullptr < lhs;
+}
+
+template <typename T>
+bool operator> (std::nullptr_t, const_propogating_ptr<T> const&rhs) {
+  return rhs < nullptr;
+}
+
+template <typename T>
+bool operator<=(const_propogating_ptr<T> const&lhs, std::nullptr_t) {
+  return !(nullptr < lhs);
+}
+
+template <typename T>
+bool operator<=(std::nullptr_t, const_propogating_ptr<T> const&rhs) {
+  return !(rhs < nullptr);
+}
+
+template <typename T>
+bool operator>=(const_propogating_ptr<T> const&lhs, std::nullptr_t) {
+  return !(lhs < nullptr);
+}
+
+template <typename T>
+bool operator>=(std::nullptr_t, const_propogating_ptr<T> const&rhs) {
+  return !(nullptr < rhs);
+}

+ 34 - 0
const_ptr.hpp

@@ -0,0 +1,34 @@
+//
+//  const_ptr.hpp
+//  pointers
+//
+//  Created by Sam Jaffe on 1/5/17.
+//
+
+#pragma once
+#include <memory>
+
+#include "pointer_fwd.hpp"
+
+template <typename P>
+class const_ptr {
+public:
+  using element_type = typename std::pointer_traits<T>::element_type;
+  using pointer = element_type const *;
+  using reference = element_type const &;
+
+  const_ptr() : _ptr(nullptr) {}
+  const_ptr(T const & p) : _ptr(p) {}
+  const_ptr(T && p) : _ptr(std::move(p)) {}
+  
+  template <typename Y>
+  explicit operator const_ptr<Y>() & {
+    return _ptr;
+  }
+
+  reference operator*() { return *_ptr; }
+  pointer get() { return std::addressof(operator*()); }
+  pointer operator->() { return get(); }
+private:
+  P _ptr;
+};

+ 152 - 0
copy_ptr.hpp

@@ -0,0 +1,152 @@
+//
+//  copy_ptr.hpp
+//  pointers
+//
+//  Created by Sam Jaffe on 12/6/16.
+//
+
+#pragma once
+
+#include <functional>
+#include <memory>
+
+#include "pointer_fwd.hpp"
+
+namespace detail {
+  template <typename T>
+  T * copy_ptr_from_ptr(T * ptr) {
+    return ptr ? new T(*ptr) : nullptr;
+  }
+}
+
+template <typename T, T*(*Copy)(T*) = &detail::copy_ptr_from_ptr<T> >
+class copy_ptr {
+public:
+  using element_type = T;
+  using pointer = element_type *;
+  using reference = element_type &;
+  
+  copy_ptr() : _ptr(nullptr) {}
+  copy_ptr(P const & p) = delete;
+  copy_ptr(P && p) : _ptr(std::move(p)) {}
+  copy_ptr(copy_ptr const & other) : _ptr(Copy(other._ptr)) {}
+  copy_ptr(copy_ptr &&) = default;
+  
+  template <typename Y>
+  explicit operator copy_ptr<Y>() const {
+    return Copy(_ptr);
+  }
+  
+  ~copy_ptr() { delete _ptr; }
+  
+  copy_ptr & operator=(copy_ptr const & other) {
+    swap(copy_ptr{other});
+    return *this;
+  }
+  copy_ptr & operator=(copy_ptr &&) = default;
+  
+  operator bool() const {
+    return static_cast<bool>(_ptr);
+  }
+  
+  pointer get() const { return _ptr; }
+  pointer operator->() const { return get(); }
+  reference operator*() const { return *get(); }
+private:
+  P _ptr;
+};
+
+template <typename T, typename U>
+bool operator==(copy_ptr<T> const&lhs, copy_ptr<U> const&rhs) {
+  return lhs.get() == rhs.get();
+}
+
+template <typename T, typename U>
+bool operator!=(copy_ptr<T> const&lhs, copy_ptr<U> const&rhs) {
+  return !(lhs == rhs);
+}
+
+template <typename T, typename U>
+bool operator< (copy_ptr<T> const&lhs, copy_ptr<U> const&rhs) {
+  typedef typename std::common_type<
+  typename copy_ptr<T>::pointer,
+  typename copy_ptr<U>::pointer>::type V;
+  return std::less<V>(lhs.get(), rhs.get());
+}
+
+template <typename T, typename U>
+bool operator> (copy_ptr<T> const&lhs, copy_ptr<U> const&rhs) {
+  return rhs < lhs;
+}
+
+template <typename T, typename U>
+bool operator<=(copy_ptr<T> const&lhs, copy_ptr<U> const&rhs) {
+  return !(rhs < lhs);
+}
+
+template <typename T, typename U>
+bool operator>=(copy_ptr<T> const&lhs, copy_ptr<U> const&rhs) {
+  return !(lhs < rhs);
+}
+
+template <typename T>
+bool operator==(copy_ptr<T> const&lhs, std::nullptr_t) {
+  return !lhs;
+}
+
+template <typename T>
+bool operator==(std::nullptr_t, copy_ptr<T> const&rhs) {
+  return !rhs;
+}
+
+template <typename T>
+bool operator!=(copy_ptr<T> const&lhs, std::nullptr_t) {
+  return static_cast<bool>(lhs);
+}
+
+template <typename T>
+bool operator!=(std::nullptr_t, copy_ptr<T> const&rhs) {
+  return static_cast<bool>(rhs);
+}
+
+template <typename T>
+bool operator< (copy_ptr<T> const&lhs, std::nullptr_t) {
+  typedef typename copy_ptr<T>::pointer V;
+  return std::less<V>(lhs.get(), nullptr);
+}
+
+template <typename T>
+bool operator< (std::nullptr_t, copy_ptr<T> const&rhs) {
+  typedef typename copy_ptr<T>::pointer V;
+  return std::less<V>(nullptr, rhs.get());
+}
+
+template <typename T>
+bool operator> (copy_ptr<T> const&lhs, std::nullptr_t) {
+  return nullptr < lhs;
+}
+
+template <typename T>
+bool operator> (std::nullptr_t, copy_ptr<T> const&rhs) {
+  return rhs < nullptr;
+}
+
+template <typename T>
+bool operator<=(copy_ptr<T> const&lhs, std::nullptr_t) {
+  return !(nullptr < lhs);
+}
+
+template <typename T>
+bool operator<=(std::nullptr_t, copy_ptr<T> const&rhs) {
+  return !(rhs < nullptr);
+}
+
+template <typename T>
+bool operator>=(copy_ptr<T> const&lhs, std::nullptr_t) {
+  return !(lhs < nullptr);
+}
+
+template <typename T>
+bool operator>=(std::nullptr_t, copy_ptr<T> const&rhs) {
+  return !(nullptr < rhs);
+}

+ 2 - 0
pointer_fwd.hpp

@@ -10,6 +10,8 @@
 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;
 
 class unchecked_pointer_exception;
 class null_pointer_exception;