static_function_deleter.
authorYedidya Feldblum <yfeldblum@fb.com>
Fri, 21 Aug 2015 22:24:06 +0000 (15:24 -0700)
committerfacebook-github-bot-9 <folly-bot@fb.com>
Fri, 21 Aug 2015 23:20:21 +0000 (16:20 -0700)
Summary: [Folly] static_function_deleter.

So you can write this:

    using BIO_deleter = folly::static_function_deleter<BIO, &BIO_free>;
    auto buf = std::unique_ptr<BIO, BIO_deleter>(BIO_new(BIO_s_mem()));
    buf = nullptr;

In place of this:

    struct BIO_deleter {
      void operator()(BIO* bio) {
        BIO_free(bio);
      }
    };
    auto buf = std::unique_ptr<BIO, BIO_deleter>(BIO_new(BIO_s_mem()));
    buf = nullptr;

Reviewed By: @alandau

Differential Revision: D2364544

folly/Memory.h
folly/test/MemoryTest.cpp

index 70bc451cb2221bad6ef984f4018613bdc4859135..76f11dc155b5ae26d148aff07e8573cd990fbeab 100644 (file)
@@ -56,6 +56,21 @@ typename std::enable_if<
   std::extent<T>::value != 0, std::unique_ptr<T, Dp>>::type
 make_unique(Args&&...) = delete;
 
+/**
+ * static_function_deleter
+ *
+ * So you can write this:
+ *
+ *      using BIO_deleter = folly::static_function_deleter<BIO, &BIO_free>;
+ *      auto buf = std::unique_ptr<BIO, BIO_deleter>(BIO_new(BIO_s_mem()));
+ *      buf = nullptr;  // calls BIO_free(buf.get())
+ */
+
+template <typename T, void(*f)(T*)>
+struct static_function_deleter {
+  void operator()(T* t) { f(t); }
+};
+
 /**
  *  to_shared_ptr
  *
index c9a2b0ea6d95c3bd70717cd76852f729b25f5ce1..03c53ee7508474af90e2a910b3b6b7ec0cd980af 100644 (file)
 
 using namespace folly;
 
+namespace {
+class disposable {
+ public:
+  explicit disposable(std::function<void()> onDispose) :
+    onDispose_(std::move(onDispose)) {}
+  static void dispose(disposable* f) {
+    ASSERT_NE(nullptr, f);
+    f->onDispose_();
+    delete f;
+  }
+ private:
+  std::function<void()> onDispose_;
+};
+}
+
+TEST(static_function_deleter, example) {
+  size_t count = 0;
+  using disposable_deleter =
+    static_function_deleter<disposable, &disposable::dispose>;
+  make_unique<disposable, disposable_deleter>([&] { ++count; });
+  EXPECT_EQ(1, count);
+}
+
+TEST(static_function_deleter, nullptr) {
+  using disposable_deleter =
+    static_function_deleter<disposable, &disposable::dispose>;
+  std::unique_ptr<disposable, disposable_deleter>(nullptr);
+}
+
 TEST(shared_ptr, example) {
   auto uptr = make_unique<std::string>("hello");
   auto sptr = to_shared_ptr(std::move(uptr));