소스 검색

Hide details of IFD pointer copying. in a wrapper class.

Sam Jaffe 5 년 전
부모
커밋
d48b9c2dc0
2개의 변경된 파일77개의 추가작업 그리고 46개의 파일을 삭제
  1. 48 0
      include/stream/streams/ifd_pointer.hpp
  2. 29 46
      include/stream/streams/streams.hpp

+ 48 - 0
include/stream/streams/ifd_pointer.hpp

@@ -0,0 +1,48 @@
+#pragma once
+
+namespace stream { namespace detail {
+  class ifd_pointer {
+  private:
+    void * (*copy)(void *){nullptr};
+    void (*destroy)(void *){nullptr};
+    void * ptr{nullptr};
+
+  public:
+    template <typename T>
+    ifd_pointer(T && value)
+        : copy(&ifd_pointer::copy_<T>), destroy(&ifd_pointer::destroy_<T>),
+          ptr(copy(&value)) {}
+
+    ifd_pointer() = default;
+    ifd_pointer(ifd_pointer const & other)
+        : copy(other.copy), destroy(other.destroy), ptr(copy(other.ptr)) {}
+    ifd_pointer(ifd_pointer && other) {
+      *this = std::forward<ifd_pointer>(other);
+    }
+    ifd_pointer & operator=(ifd_pointer const & other) {
+      return *this = ifd_pointer(other);
+    }
+    ~ifd_pointer() {
+      if (destroy) destroy(ptr);
+    }
+
+    ifd_pointer & operator=(ifd_pointer && other) {
+      swap(*this, other);
+      return *this;
+    }
+
+    void * get() const { return ptr; }
+
+  private:
+    friend void swap(ifd_pointer & lhs, ifd_pointer & rhs) {
+      using ::std::swap;
+      swap(lhs.copy, rhs.copy);
+      swap(lhs.destroy, rhs.destroy);
+      swap(lhs.ptr, rhs.ptr);
+    }
+    template <typename T> static void * copy_(void * p) {
+      return (void *)new T(*(T *)(p));
+    }
+    template <typename T> static void destroy_(void * p) { delete (T *)(p); }
+  };
+}}

+ 29 - 46
include/stream/streams/streams.hpp

@@ -5,11 +5,9 @@
 #include <numeric>
 #include <vector>
 
-namespace stream {
-#define STREAM_ITERATOR_COPY()                                                 \
-  copy(other.copy), dereference(other.dereference), compare(other.compare),    \
-      destroy(other.destroy), advance(other.advance), type_(other.type_)
+#include "ifd_pointer.hpp"
 
+namespace stream {
   template <typename T> class iterator {
   public:
     using value_type = typename std::remove_reference<T>::type;
@@ -18,71 +16,56 @@ namespace stream {
     using difference_type = std::ptrdiff_t;
     using iterator_category = std::forward_iterator_tag;
 
+  private:
+    T (*dereference)(void *){nullptr};
+    bool (*compare)(void *, void *){nullptr};
+    void (*advance)(void *){nullptr};
+    char const * type_{nullptr};
+    detail::ifd_pointer impl_{};
+
   public:
     iterator() = default;
 
-    template <typename Iter> iterator(Iter impl) {
-      copy = [](void * p) { return (void *)new Iter(*(Iter *)(p)); };
-      dereference = [](void * p) -> T { return **((Iter *)p); };
-      compare = [](void * l, void * r) { return *((Iter *)l) == *((Iter *)r); };
-      destroy = [](void * p) { delete (Iter *)(p); };
-      advance = [](void * p) { ++(*(Iter *)(p)); };
-      type_ = typeid(Iter).name();
-      impl_ = copy(&impl);
-    }
-
-    iterator(iterator const & other)
-        : STREAM_ITERATOR_COPY(), impl_(copy(other.impl_)) {}
-
-    iterator(iterator && other) : STREAM_ITERATOR_COPY(), impl_(other.impl_) {
-      other.impl_ = nullptr;
-    }
-
-    iterator & operator=(iterator const & other) {
-      return *this = iterator{other};
-    }
-
-    iterator & operator=(iterator && other) {
-      swap(*this, other);
-      return *this;
-    }
+    template <typename Iter>
+    iterator(Iter impl)
+        : dereference(&iterator::dereference_<Iter>),
+          compare(&iterator::compare_<Iter>),
+          advance(&iterator::advance_<Iter>), type_(typeid(Iter).name()),
+          impl_(std::forward<Iter>(impl)) {}
 
-    ~iterator() {
-      if (destroy) destroy(impl_);
-    }
-
-    T operator*() const { return dereference(impl_); }
+    T operator*() const { return dereference(impl_.get()); }
     iterator & operator++() {
-      advance(impl_);
+      advance(impl_.get());
       return *this;
     }
+
     bool operator==(iterator const & other) const {
       if (strcmp(type_, other.type_)) { return false; }
-      return compare(impl_, other.impl_);
+      return compare(impl_.get(), other.impl_.get());
     }
+
     bool operator!=(iterator const & other) const {
       if (strcmp(type_, other.type_)) { return false; }
-      return !compare(impl_, other.impl_);
+      return !compare(impl_.get(), other.impl_.get());
     }
 
   private:
     friend void swap(iterator & lhs, iterator & rhs) {
       using std::swap;
-      swap(lhs.copy, rhs.copy);
       swap(lhs.dereference, rhs.dereference);
       swap(lhs.compare, rhs.compare);
-      swap(lhs.destroy, rhs.destroy);
       swap(lhs.advance, rhs.advance);
       swap(lhs.type_, rhs.type_);
       swap(lhs.impl_, rhs.impl_);
     }
-    using delegate = void (*)(void *);
-    void * (*copy)(void *){nullptr};
-    T (*dereference)(void *){nullptr};
-    bool (*compare)(void *, void *){nullptr};
-    delegate destroy{nullptr}, advance{nullptr};
-    char const * type_{nullptr};
-    void * impl_{nullptr};
+
+    template <typename It> static T dereference_(void * p) {
+      return **((It *)p);
+    }
+    template <typename It> static bool compare_(void * l, void * r) {
+      return *((It *)l) == *((It *)r);
+    }
+    template <typename It> static void advance_(void * p) { ++(*(It *)(p)); }
   };
 
   namespace detail {