Jelajahi Sumber

Rename copy_ptr value_ptr

Samuel Jaffe 8 tahun lalu
induk
melakukan
6df63a029e
4 mengubah file dengan 139 tambahan dan 102 penghapusan
  1. 0 78
      copy_ptr.hpp
  2. 6 5
      pointers.xcodeproj/project.pbxproj
  3. 83 0
      value_ptr.hpp
  4. 50 19
      copy_ptr.t.h

+ 0 - 78
copy_ptr.hpp

@@ -1,78 +0,0 @@
-//
-//  copy_ptr.hpp
-//  pointers
-//
-//  Created by Sam Jaffe on 12/6/16.
-//
-
-#pragma once
-
-#include <memory>
-
-#include "pointer_fwd.hpp"
-#include "ptr_compare.hpp"
-
-namespace detail {
-  template <typename T>
-  T * copy_ptr_from_ptr(T const * ptr) {
-    return ptr ? new T(*ptr) : nullptr;
-  }
-  
-  template <typename T>
-  using clone_func = T* (T::*)() const;
-  
-  template <typename T, clone_func<T> Clone>
-  T * clone_ptr_from_ptr(T const * ptr) {
-    return ptr ? (ptr->*Clone)() : nullptr;
-  }
-}
-
-template <typename T, T*(*Copy)(T const *) = &detail::copy_ptr_from_ptr<T> >
-class copy_ptr {
-public:
-  using element_type = T;
-  using pointer = element_type *;
-  using reference = element_type &;
-  
-  copy_ptr() noexcept : _ptr(nullptr) {}
-  copy_ptr(T * const & p) = delete;
-  copy_ptr(T * && p) noexcept(std::is_nothrow_move_constructible<T>::value) : _ptr(std::move(p)) {}
-  copy_ptr(copy_ptr const & other) : _ptr(Copy(other._ptr)) {}
-  copy_ptr(copy_ptr && other) noexcept(noexcept(swap(_ptr, other._ptr))) : _ptr(nullptr) { swap(_ptr, other._ptr); }
-  static copy_ptr copy_of(T * const & p) {
-    return Copy(p);
-  }
-  
-  template <typename Y>
-  explicit operator copy_ptr<Y>() const {
-    return Copy(_ptr);
-  }
-  
-  ~copy_ptr() { delete _ptr; }
-  
-  copy_ptr & operator=(copy_ptr const & other) noexcept(noexcept(swap(_ptr, other._ptr))) {
-    swap(_ptr, copy_ptr{other}._ptr);
-    return *this;
-  }
-  copy_ptr & operator=(copy_ptr && other) noexcept(noexcept(swap(_ptr, other._ptr))) {
-    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:
-  T * _ptr;
-};
-
-template <typename T, detail::clone_func<T> Clone>
-using clone_ptr = copy_ptr<T, &detail::clone_ptr_from_ptr<T, Clone>>;
-
-POINTER_TEMPLATE_COMPARE_FULL( copy_ptr,
-      (typename T1, T1*(*C1)(T1*)), (T1, C1),
-      (typename T2, T2*(*C2)(T2*)), (T2, C2))

+ 6 - 5
pointers.xcodeproj/project.pbxproj

@@ -25,7 +25,7 @@
 /* Begin PBXFileReference section */
 		CD0364691E1F3F0B003B7B84 /* const_propogating_ptr.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = const_propogating_ptr.t.h; sourceTree = "<group>"; };
 		CD03646A1E1F41DE003B7B84 /* const_ptr.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = const_ptr.t.h; sourceTree = "<group>"; };
-		CD03646B1E1F42A1003B7B84 /* copy_ptr.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = copy_ptr.t.h; sourceTree = "<group>"; };
+		CD03646B1E1F42A1003B7B84 /* value_ptr.t.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = value_ptr.t.h; sourceTree = "<group>"; };
 		CD125DD81E1F00C200B53FB5 /* const_ptr.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = const_ptr.hpp; sourceTree = "<group>"; };
 		CD125DDA1E1F1B7500B53FB5 /* ptr_compare.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = ptr_compare.hpp; sourceTree = "<group>"; };
 		CD3DA3F21D9B42BC001B53A0 /* pointers_tc */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = pointers_tc; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -36,7 +36,7 @@
 		CDC3B0E51DF26319002A415B /* pointers_tc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pointers_tc.cpp; sourceTree = "<group>"; };
 		CDC3B0E71DF263B2002A415B /* maybe_null.t.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = maybe_null.t.h; sourceTree = "<group>"; };
 		CDC3B0E81DF3645F002A415B /* const_propogating_ptr.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = const_propogating_ptr.hpp; sourceTree = "<group>"; };
-		CDC3B0E91DF794A6002A415B /* copy_ptr.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = copy_ptr.hpp; sourceTree = "<group>"; };
+		CDC3B0E91DF794A6002A415B /* value_ptr.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = value_ptr.hpp; sourceTree = "<group>"; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
@@ -55,7 +55,7 @@
 			children = (
 				CD0364691E1F3F0B003B7B84 /* const_propogating_ptr.t.h */,
 				CD03646A1E1F41DE003B7B84 /* const_ptr.t.h */,
-				CD03646B1E1F42A1003B7B84 /* copy_ptr.t.h */,
+				CD03646B1E1F42A1003B7B84 /* value_ptr.t.h */,
 				CDC3B0E31DF261D7002A415B /* not_null.t.h */,
 				CDC3B0E71DF263B2002A415B /* maybe_null.t.h */,
 				CDC3B0E51DF26319002A415B /* pointers_tc.cpp */,
@@ -68,7 +68,7 @@
 			children = (
 				CD3DA3FC1D9B42DE001B53A0 /* pointer_fwd.hpp */,
 				CD125DDA1E1F1B7500B53FB5 /* ptr_compare.hpp */,
-				CDC3B0E91DF794A6002A415B /* copy_ptr.hpp */,
+				CDC3B0E91DF794A6002A415B /* value_ptr.hpp */,
 				CD125DD81E1F00C200B53FB5 /* const_ptr.hpp */,
 				CDC3B0E81DF3645F002A415B /* const_propogating_ptr.hpp */,
 				CD3DA3FE1D9B42DE001B53A0 /* maybe_null.hpp */,
@@ -157,13 +157,14 @@
 				"$(SRCROOT)/maybe_null.t.h",
 				"$(SRCROOT)/const_propogating_ptr.t.h",
 				"$(SRCROOT)/const_ptr.t.h",
+				"$(SRCROOT)/value_ptr.t.h",
 			);
 			outputPaths = (
 				"$(SRCROOT)/pointers_tc.cpp",
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "cxxtestgen --error-printer -o pointers_tc.cpp not_null.t.h maybe_null.t.h const_propogating_ptr.t.h const_ptr.t.h copy_ptr.t.h";
+			shellScript = "cxxtestgen --error-printer -o pointers_tc.cpp not_null.t.h maybe_null.t.h const_propogating_ptr.t.h const_ptr.t.h value_ptr.t.h";
 		};
 /* End PBXShellScriptBuildPhase section */
 

+ 83 - 0
value_ptr.hpp

@@ -0,0 +1,83 @@
+//
+//  copy_ptr.hpp
+//  pointers
+//
+//  Created by Sam Jaffe on 12/6/16.
+//
+
+#pragma once
+
+#include <memory>
+
+#include "pointer_fwd.hpp"
+#include "ptr_compare.hpp"
+
+namespace detail {
+  template <typename T>
+  using clone_func = T* (T::*)() const;
+  
+  template <typename T, typename = void>
+  class value_ptr_copy;
+  
+  template <typename T>
+  struct value_ptr_copy<T, typename std::enable_if<!std::is_polymorphic<T>::value>::type> {
+    T * Copy( T * ptr ) const { return ptr ? new T(*ptr) : nullptr; }
+  };
+
+#define POLYMORPHIC_VALUE_PTR_GROUP_FROM_CLONE_FUNCTION( fclone ) \
+  template <typename T> \
+  struct value_ptr_copy<T, typename std::enable_if<std::is_polymorphic<T>::value \
+      && std::is_same<clone_func<T>, decltype(&T::fclone)>::value>::type> { \
+    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(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) noexcept(noexcept(swap(_ptr, other._ptr))) {
+    swap(_ptr, value_ptr{other}._ptr);
+    return *this;
+  }
+  value_ptr & operator=(value_ptr && other) noexcept(noexcept(swap(_ptr, other._ptr))) {
+    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:
+  T * _ptr;
+};
+
+POINTER_TEMPLATE_COMPARE( value_ptr )

+ 50 - 19
copy_ptr.t.h

@@ -11,16 +11,23 @@
 
 #include <stdexcept>
 
-#include "copy_ptr.hpp"
+#include "value_ptr.hpp"
+
+struct copy_me {};
+struct copy_me_throw {};
+
+namespace detail {
+  template<> class value_ptr_copy<copy_me_throw> {
+  protected:
+    copy_me_throw * Copy(copy_me_throw const * p) const {
+      if (p == nullptr) { throw std::runtime_error{"NULL"}; }
+      return new copy_me_throw{*p};
+    }
+  };
+}
 
 class copy_ptr_TestSuite : public CxxTest::TestSuite {
 private:
-  struct copy_me {};
-  
-  static copy_me * throw_clone(copy_me const * p) {
-    if (p == nullptr) { throw std::runtime_error{"NULL"}; }
-    return new copy_me{*p};
-  }
 
   class base {
   public:
@@ -44,27 +51,27 @@ private:
   };
 public:
   void test_copy_new_obj() {
-    copy_ptr<copy_me> c1 { new copy_me };
-    copy_ptr<copy_me> c2 { c1 };
+    value_ptr<copy_me> c1 { new copy_me };
+    value_ptr<copy_me> c2 { c1 };
     TS_ASSERT_DIFFERS( c1.get(), c2.get() );
   }
   
   void test_copy_with_nullptr() {
-    copy_ptr<copy_me> c1 { nullptr };
-    copy_ptr<copy_me> c2 { c1 };
+    value_ptr<copy_me> c1 { nullptr };
+    value_ptr<copy_me> c2 { c1 };
     TS_ASSERT_EQUALS( c1.get(), nullptr );
     TS_ASSERT_EQUALS( c1.get(), c2.get() );
   }
 
   void test_copy_custom_func() {
-    using ptr_t = copy_ptr<copy_me, &copy_ptr_TestSuite::throw_clone>;
-    ptr_t c1 { new copy_me };
+    using ptr_t = value_ptr<copy_me_throw>;
+    ptr_t c1 { new copy_me_throw };
     ptr_t c2 { c1 };
     TS_ASSERT_DIFFERS( c1.get(), c2.get() );
   }
 
   void test_copy_custom_func_with_nullptr() {
-    using ptr_t = copy_ptr<copy_me, &copy_ptr_TestSuite::throw_clone>;
+    using ptr_t = value_ptr<copy_me_throw>;
     ptr_t c1 { nullptr };
     TS_ASSERT_THROWS( ptr_t{ c1 }, std::runtime_error );
   }
@@ -72,14 +79,14 @@ public:
   void test_copy_object_is_deep_equals() {
     using vec_t = std::vector<int>;
     vec_t my_vec = { 1, 3, 5, 3, 6, 1, 2, -1, 0 };
-    copy_ptr<vec_t> c1{ new vec_t{ my_vec } };
+    value_ptr<vec_t> c1{ new vec_t{ my_vec } };
     TS_ASSERT_EQUALS( *c1, my_vec );
-    copy_ptr<vec_t> c2{ c1 };
+    value_ptr<vec_t> c2{ c1 };
     TS_ASSERT_EQUALS( *c2, *c1 );
   }
   
   void test_clone_polymorpic_object() {
-    using ptr_t = clone_ptr<base, &base::clone>;
+    using ptr_t = value_ptr<base>;
     ptr_t c0 { new derived_0 };
     TS_ASSERT_EQUALS( ptr_t( c0 )->id(), derived_0::ID);
     ptr_t c1 { new derived_1 };
@@ -87,7 +94,7 @@ public:
   }
   
   void test_clone_polymorphic_with_nullptr() {
-    using ptr_t = clone_ptr<base, &base::clone>;
+    using ptr_t = value_ptr<base>;
     ptr_t c1 { nullptr };
     ptr_t c2 { c1 };
     TS_ASSERT_EQUALS( c1.get(), nullptr );
@@ -101,7 +108,31 @@ public:
       bool & _r;
     };
     test_t * test_struct = new test_t{has_delete};
-    copy_ptr<test_t, nullptr>{ std::move(test_struct) };
+    TS_ASSERT_THROWS_NOTHING(value_ptr<test_t>{ std::move(test_struct) });
     TS_ASSERT_EQUALS(has_delete, true);
   }
+
+  void test_does_own_temporary() const {
+    bool has_delete{false};
+    struct test_t {
+      ~test_t() { _r = true; }
+      bool & _r;
+    };
+    TS_ASSERT_THROWS_NOTHING(value_ptr<test_t>{ new test_t{has_delete} });
+    TS_ASSERT_EQUALS(has_delete, true);
+  }
+
+  void test_does_copy_on_copy() const {
+    int deleted{0};
+    struct test_t {
+      ~test_t() { ++(*_r); }
+      int * _r;
+    };
+    {
+      std::unique_ptr<test_t> test_struct{new test_t{&deleted}};
+      TS_ASSERT_THROWS_NOTHING(value_ptr<test_t>::copy_of( test_struct.get() ));
+      TS_ASSERT_EQUALS(deleted, 1);
+    }
+    TS_ASSERT_EQUALS(deleted, 2);
+  }
 };