浏览代码

Expanding copy_ptr to support "copiable polymorphic objects" that provide a clone method. Adding a test case for copy_ptr.

Samuel Jaffe 9 年之前
父节点
当前提交
766c6e63bd
共有 2 个文件被更改,包括 71 次插入99 次删除
  1. 19 99
      copy_ptr.hpp
  2. 52 0
      copy_ptr.t.h

+ 19 - 99
copy_ptr.hpp

@@ -7,19 +7,27 @@
 
 #pragma once
 
-#include <functional>
 #include <memory>
 
 #include "pointer_fwd.hpp"
+#include "ptr_compare.hpp"
 
 namespace detail {
   template <typename T>
-  T * copy_ptr_from_ptr(T * ptr) {
+  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*) = &detail::copy_ptr_from_ptr<T> >
+template <typename T, T*(*Copy)(T const *) = &detail::copy_ptr_from_ptr<T> >
 class copy_ptr {
 public:
   using element_type = T;
@@ -27,8 +35,8 @@ public:
   using reference = element_type &;
   
   copy_ptr() : _ptr(nullptr) {}
-  copy_ptr(P const & p) = delete;
-  copy_ptr(P && p) : _ptr(std::move(p)) {}
+  copy_ptr(T * const & p) = delete;
+  copy_ptr(T * && p) : _ptr(std::move(p)) {}
   copy_ptr(copy_ptr const & other) : _ptr(Copy(other._ptr)) {}
   copy_ptr(copy_ptr &&) = default;
   
@@ -53,100 +61,12 @@ public:
   pointer operator->() const { return get(); }
   reference operator*() const { return *get(); }
 private:
-  P _ptr;
+  T * _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, detail::clone_func<T> Clone>
+using clone_ptr = copy_ptr<T, &detail::clone_ptr_from_ptr<T, Clone>>;
 
-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);
-}
+POINTER_TEMPLATE_COMPARE_FULL( copy_ptr,
+      (typename T1, T1*(*C1)(T1*)), (T1, C1),
+      (typename T2, T2*(*C2)(T2*)), (T2, C2))

+ 52 - 0
copy_ptr.t.h

@@ -0,0 +1,52 @@
+//
+//  copy_ptr.t.h
+//  pointers
+//
+//  Created by Sam Jaffe on 1/5/17.
+//
+
+#pragma once
+
+#include <cxxtest/TestSuite.h>
+
+#include "copy_ptr.hpp"
+
+class copy_ptr_TestSuite : public CxxTest::TestSuite {
+private:
+  struct copy_me {};
+
+  class base {
+  public:
+    virtual ~base() {}
+    virtual base* clone() const = 0;
+    virtual int id() const = 0;
+  };
+  
+  class derived_0 : public base {
+  public:
+    static const constexpr int ID = 0;
+    virtual base * clone() const override { return new derived_0; }
+    virtual int id() const override { return ID; }
+  };
+  
+  class derived_1 : public base {
+  public:
+    static const constexpr int ID = 1;
+    virtual base * clone() const override { return new derived_1; }
+    virtual int id() const override { return ID; }
+  };
+public:
+  void test_copy_new_obj() {
+    copy_ptr<copy_me> c1 { new copy_me };
+    copy_ptr<copy_me> c2 { c1 };
+    TS_ASSERT_DIFFERS( c1.get(), c2.get() );
+  }
+  
+  void test_clone_polymorpic_object() {
+    using ptr_t = clone_ptr<base, &base::clone>;
+    ptr_t c0 { new derived_0 };
+    TS_ASSERT_EQUALS( ptr_t( c0 )->id(), derived_0::ID);
+    ptr_t c1 { new derived_1 };
+    TS_ASSERT_EQUALS( ptr_t( c1 )->id(), derived_1::ID);
+  }
+};