Browse Source

Fixing noexcept and swap behavior for assignment operators in value_ptr.
Adding 'construct from constructable' thing to annotation-type pointers. This allows things like:
std::map<K, const_propogating_ptr<not_null<value_ptr<Object>>>> map;
map.emplace(key, make_value<Object>())
without any copies.

Samuel Jaffe 8 years ago
parent
commit
bc5fc281e8
5 changed files with 33 additions and 7 deletions
  1. 5 1
      const_propogating_ptr.hpp
  2. 5 1
      const_ptr.hpp
  3. 5 1
      maybe_null.hpp
  4. 6 2
      not_null.hpp
  5. 12 2
      value_ptr.hpp

+ 5 - 1
const_propogating_ptr.hpp

@@ -23,7 +23,11 @@ public:
   const_propogating_ptr() noexcept : _ptr(nullptr) {}
   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::move(p)) { }
+
   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;

+ 5 - 1
const_ptr.hpp

@@ -21,7 +21,11 @@ public:
   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::move(p)) { }
+
   template <typename Y>
   explicit operator const_ptr<Y>() const noexcept(detail::is_nt_c<P, Y>::value) {
     return _ptr;

+ 5 - 1
maybe_null.hpp

@@ -35,6 +35,10 @@ public:
   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::move(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>
@@ -62,7 +66,7 @@ public:
   }
   
   void reset( P const & p ) { operator=(maybe_null(p)); }
-  void reset( P && p = P() ) { operator=(maybe_null(std::forward(p))); }
+  void reset( P && p = P() ) { operator=(maybe_null(std::move(p))); }
 private:
   template <typename Y> friend class maybe_null;
   P _ptr;

+ 6 - 2
not_null.hpp

@@ -27,8 +27,12 @@ public:
   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::move(p)) { validate(); }
   not_null(not_null const&) noexcept(detail::is_nt_cc<P>::value) = default;
-  not_null(not_null &&) = delete;
+//  not_null(not_null &&) = delete;
   
   template <typename Y>
   explicit operator maybe_null<Y>() const noexcept(detail::is_nt_c<Y, P>::value) {
@@ -40,7 +44,7 @@ public:
   }
 
   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 &&) = delete;
   
   operator bool() const noexcept { return true; }
   

+ 12 - 2
value_ptr.hpp

@@ -60,11 +60,11 @@ public:
   
   ~value_ptr() { delete _ptr; }
   
-  value_ptr & operator=(value_ptr const & other) noexcept(noexcept(swap(_ptr, other._ptr))) {
+  value_ptr & operator=(value_ptr const & other) {
     swap(_ptr, value_ptr{other}._ptr);
     return *this;
   }
-  value_ptr & operator=(value_ptr && other) noexcept(noexcept(swap(_ptr, other._ptr))) {
+  value_ptr & operator=(value_ptr && other) noexcept {
     swap(_ptr, other._ptr);
     return *this;
   }
@@ -77,7 +77,17 @@ public:
   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;
 };
 
+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 )