Converge folly::make_unique to C++14's std::make_unique
authorYedidya Feldblum <yfeldblum@fb.com>
Sat, 3 Oct 2015 04:47:38 +0000 (21:47 -0700)
committerfacebook-github-bot-9 <folly-bot@fb.com>
Sat, 3 Oct 2015 05:20:19 +0000 (22:20 -0700)
Summary: [Folly] Converge `folly::make_unique` to C++14's `std::make_unique`.

The primary use-case of ther deleter variety of `folly::make_unique` is `DelayedDestruction`. Let the classes matching this use-case define their own factories.

Reviewed By: @fugalh

Differential Revision: D2495718

folly/Memory.h
folly/io/async/AsyncPipe.h
folly/io/async/HHWheelTimer.h
folly/io/async/test/AsyncPipeTest.cpp
folly/test/MemoryTest.cpp

index b58edf20a03aee7c1c4fe591dacc2b950250ad93..eadc1c816292db2e5802f46cebff3a78eaa807c7 100644 (file)
@@ -37,25 +37,33 @@ namespace folly {
  * @author Xu Ning (xning@fb.com)
  */
 
-template<typename T, typename Dp = std::default_delete<T>, typename... Args>
-typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T, Dp>>::type
+#if __cplusplus >= 201402L
+
+/* using override */ using std::make_unique;
+
+#else
+
+template<typename T, typename... Args>
+typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type
 make_unique(Args&&... args) {
-  return std::unique_ptr<T, Dp>(new T(std::forward<Args>(args)...));
+  return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
 }
 
 // Allows 'make_unique<T[]>(10)'. (N3690 s20.9.1.4 p3-4)
-template<typename T, typename Dp = std::default_delete<T>>
-typename std::enable_if<std::is_array<T>::value, std::unique_ptr<T, Dp>>::type
+template<typename T>
+typename std::enable_if<std::is_array<T>::value, std::unique_ptr<T>>::type
 make_unique(const size_t n) {
-  return std::unique_ptr<T, Dp>(new typename std::remove_extent<T>::type[n]());
+  return std::unique_ptr<T>(new typename std::remove_extent<T>::type[n]());
 }
 
 // Disallows 'make_unique<T[10]>()'. (N3690 s20.9.1.4 p5)
-template<typename T, typename Dp = std::default_delete<T>, typename... Args>
+template<typename T, typename... Args>
 typename std::enable_if<
-  std::extent<T>::value != 0, std::unique_ptr<T, Dp>>::type
+  std::extent<T>::value != 0, std::unique_ptr<T>>::type
 make_unique(Args&&...) = delete;
 
+#endif
+
 /**
  * static_function_deleter
  *
index 63e73acb4aace853ca5d6c18e3a4510543b0bc36..40d5021a19aa92286ffa9784f751215a4c29453d 100644 (file)
@@ -37,6 +37,11 @@ class AsyncPipeReader : public EventHandler,
   typedef std::unique_ptr<AsyncPipeReader,
                           folly::DelayedDestruction::Destructor> UniquePtr;
 
+  template <typename... Args>
+  static UniquePtr newReader(Args&&... args) {
+    return UniquePtr(new AsyncPipeReader(std::forward<Args>(args)...));
+  }
+
   AsyncPipeReader(folly::EventBase* eventBase, int pipeFd)
     : EventHandler(eventBase, pipeFd),
     fd_(pipeFd) {}
@@ -93,6 +98,11 @@ class AsyncPipeWriter : public EventHandler,
   typedef std::unique_ptr<AsyncPipeWriter,
                           folly::DelayedDestruction::Destructor> UniquePtr;
 
+  template <typename... Args>
+  static UniquePtr newWriter(Args&&... args) {
+    return UniquePtr(new AsyncPipeWriter(std::forward<Args>(args)...));
+  }
+
   AsyncPipeWriter(folly::EventBase* eventBase, int pipeFd)
     : EventHandler(eventBase, pipeFd),
     fd_(pipeFd) {}
index 22824c22cb5365591a8e4f1783f8f2b5cc9580ea..0609ea666a71885b6637f93dd89852600c49b28a 100644 (file)
@@ -60,6 +60,11 @@ class HHWheelTimer : private folly::AsyncTimeout,
  public:
   typedef std::unique_ptr<HHWheelTimer, Destructor> UniquePtr;
 
+  template <typename... Args>
+  static UniquePtr newTimer(Args&&... args) {
+    return UniquePtr(new HHWheelTimer(std::forward<Args>(args)...));
+  }
+
   /**
    * A callback to be notified when a timeout has expired.
    */
index 750e9aa95869ebfee0cee44e86f237906b3658c2..215d90561525b997dacb7c03745bedf005b4bd6b 100644 (file)
@@ -73,11 +73,9 @@ class AsyncPipeTest: public Test {
 
     EXPECT_EQ(::fcntl(pipeFds_[0], F_SETFL, O_NONBLOCK), 0);
     EXPECT_EQ(::fcntl(pipeFds_[1], F_SETFL, O_NONBLOCK), 0);
-    reader_ = folly::make_unique<folly::AsyncPipeReader,
-                                 folly::DelayedDestruction::Destructor>(
+    reader_ = folly::AsyncPipeReader::newReader(
       &eventBase_, pipeFds_[0]);
-    writer_ = folly::make_unique<folly::AsyncPipeWriter,
-                                 folly::DelayedDestruction::Destructor>(
+    writer_ = folly::AsyncPipeWriter::newWriter(
       &eventBase_, pipeFds_[1]);
   }
 
index a62cd11ed4a9772edccf297d945c2bffbd9423cc..5c0145885a4b57a8e6f211dafc130e0def49bbf9 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(to_shared_ptr, example) {
-  auto uptr = make_unique<std::string>("hello");
-  auto sptr = to_shared_ptr(std::move(uptr));
-  EXPECT_EQ(nullptr, uptr);
-  EXPECT_EQ("hello", *sptr);
-}
+TEST(make_unique, compatible_with_std_make_unique) {
+  //  HACK: To enforce that `folly::` is imported here.
+  to_shared_ptr(std::unique_ptr<std::string>());
 
-TEST(to_shared_ptr, example_with_dtor) {
-  bool disposed = false;
-  using disposable_deleter =
-    static_function_deleter<disposable, &disposable::dispose>;
-  auto uptr =
-    make_unique<disposable, disposable_deleter>([&] { disposed = true; });
-  EXPECT_FALSE(disposed);
-  auto sptr = to_shared_ptr(std::move(uptr));
-  EXPECT_FALSE(disposed);
-  sptr = nullptr;
-  EXPECT_TRUE(disposed);
+  using namespace std;
+  make_unique<string>("hello, world");
 }
 
 template <std::size_t> struct T {};