In OwnedPtrDeleter<T>, store a vptr for a behavior function.
[zcpointer.git] / zcpointer.h
index 9af37d6f1595dbef7e4eeb9d19f5f4a6a7cc0ba1..2301ef190e3fda8bca83a74ad1487de78f8476bb 100644 (file)
@@ -34,24 +34,42 @@ template <typename T> class ref;
 
 namespace internal {
 
+enum class OwnershipBehavior {
+  DELETE_POINTER,
+  BORROW_POINTER,
+};
+
 template <typename T>
 class OwnedPtrDeleter {
  public:
-  OwnedPtrDeleter() {}
+  OwnedPtrDeleter()
+      : refs_(),
+        finalizer_(&OwnedPtrDeleter<T>::HandleDeletePointer) {}
+
   ~OwnedPtrDeleter() {}
 
-  OwnedPtrDeleter(OwnedPtrDeleter&& other) : refs_(std::move(other.refs_)) {
+  explicit OwnedPtrDeleter(OwnershipBehavior behavior)
+      : refs_(),
+        finalizer_(behavior == OwnershipBehavior::BORROW_POINTER
+                       ? &OwnedPtrDeleter<T>::HandleBorrowPointer
+                       : &OwnedPtrDeleter<T>::HandleDeletePointer) {
+  }
+
+  OwnedPtrDeleter(OwnedPtrDeleter&& other)
+      : refs_(std::move(other.refs_)),
+        finalizer_(other.finalizer_) {
   }
 
   void operator=(const OwnedPtrDeleter& o) {
     refs_ = o.refs_;
+    finalizer_ = o.finalizer_;
   }
 
   void operator()(T* t) const {
     for (auto& ref : refs_) {
       ref->MarkDeleted();
     }
-    delete t;
+    (this->finalizer_)(t);
   }
 
  protected:
@@ -65,11 +83,18 @@ class OwnedPtrDeleter {
     refs_.remove(ref);
   }
 
+  static void HandleDeletePointer(T* t) {
+    delete t;
+  }
+
+  static void HandleBorrowPointer(T* t) {}
+
  private:
+  void (*finalizer_)(T*);
   std::forward_list<ref<T>*> refs_;
 };
 
-void RaiseUseAfterFree(const char* error) __attribute__((noreturn));
+void RaiseUseAfterFree() __attribute__((noreturn));
 
 }  // namespace internal
 
@@ -155,7 +180,7 @@ class ref {
  private:
   void CheckDeleted() const {
     if (IsDeleted()) {
-      internal::RaiseUseAfterFree("attempt to access deleted pointer");
+      internal::RaiseUseAfterFree();
     }
   }
 
@@ -171,27 +196,18 @@ class ref {
 };
 
 template <typename T>
-class member {
+class member : public T {
  public:
-  template <typename... Args>
-  explicit member(Args&&... args)
-    : t_(new T(std::forward<Args>(args)...)) {
-  }
+  using T::T;
 
   ref<T> operator&() {
-    return t_.get();
-  }
-
-  T* operator->() {
-    return t_.operator->();
-  }
-
-  const T* operator->() const {
-    return t_.operator->();
+    return ptr_.get();
   }
 
  private:
-  owned<T> t_;
+  owned<T> ptr_ = owned<T>(this,
+                           internal::OwnedPtrDeleter<T>(
+                               internal::OwnershipBehavior::BORROW_POINTER));
 };
 
 #else
@@ -203,18 +219,7 @@ template <typename T>
 using ref = T*;
 
 template <typename T>
-class member : public T {
- public:
-  using T::T;
-
-  T* operator->() {
-    return this;
-  }
-
-  const T* operator->() const {
-    return this;
-  }
-};
+using member = T;
 
 #endif