Add a tag type for in-place construction
authorAlexey Spiridonov <lesha@fb.com>
Mon, 9 Nov 2015 19:16:11 +0000 (11:16 -0800)
committerfacebook-github-bot-9 <folly-bot@fb.com>
Mon, 9 Nov 2015 20:20:21 +0000 (12:20 -0800)
Summary: Without this tag type, it's impossible to use `Synchronized` with types like:

```
struct A {
  A(int, const char*);
  A(const A&) = delete;
  A& operator=(const A&) = delete;
  A(A&&) = delete;
  A& operator=(A&&) = delete;
};
```

In-place construction solves this problem. Usage:

```
Synchronized a(construct_in_place, 5, "c");
```

Reviewed By: nbronson

Differential Revision: D2610071

fb-gh-sync-id: 251fe8f8f6a2d7484dda64cf04dcacb998145230

folly/Synchronized.h
folly/Traits.h
folly/test/SynchronizedTest.cpp
folly/test/SynchronizedTestLib-inl.h
folly/test/SynchronizedTestLib.h

index dcc5f7dd775cedb0138a6c392e6630f234d7af57..8a2f9b95c731943a44453afa12bc3b707976edbe 100644 (file)
@@ -282,6 +282,14 @@ struct Synchronized {
   explicit Synchronized(T&& rhs) noexcept(nxMoveCtor)
       : datum_(std::move(rhs)) {}
 
+  /**
+   * Lets you construct non-movable types in-place. Use the constexpr
+   * instance `construct_in_place` as the first argument.
+   */
+  template <typename... Args>
+  explicit Synchronized(construct_in_place_t, Args&&... args)
+      : datum_(std::forward<Args>(args)...) {}
+
   /**
    * The canonical assignment operator only assigns the data, NOT the
    * mutex. It locks the two objects in ascending order of their
index caeb852c3b6f3d85949398331b3a00be9a5bb9e2..16aab8d6ef1e9011b195e44f35d04e69b00144cc 100644 (file)
@@ -377,6 +377,13 @@ bool greater_than(LHS const lhs) {
   >(lhs);
 }
 
+/**
+ * Like std::piecewise_construct, a tag type & instance used for in-place
+ * construction of non-movable contained types, e.g. by Synchronized.
+ */
+struct construct_in_place_t {};
+constexpr construct_in_place_t construct_in_place{};
+
 } // namespace folly
 
 FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(std::basic_string);
index 841f2b25febb76b90b5554f17fcfc05a33a27dad..afd87f91f45f15b29804337c92071d17f2065230 100644 (file)
@@ -117,4 +117,8 @@ TYPED_TEST(SynchronizedTimedWithConstTest, TimedSynchronizeWithConst) {
   testTimedSynchronizedWithConst<TypeParam>();
 }
 
+TYPED_TEST(SynchronizedTest, InPlaceConstruction) {
+  testInPlaceConstruction<TypeParam>();
+}
+
 }
index ef4045c8c4242b8d4e0e511ac7f627cc138f1ad4..29c7421cef9c05311af1559c2d40862304cb8272 100644 (file)
@@ -339,5 +339,20 @@ template <class Mutex> void testConstCopy() {
   EXPECT_EQ(result, input);
 }
 
+struct NotCopiableNotMovable {
+  NotCopiableNotMovable(int, const char*) {}
+  NotCopiableNotMovable(const NotCopiableNotMovable&) = delete;
+  NotCopiableNotMovable& operator=(const NotCopiableNotMovable&) = delete;
+  NotCopiableNotMovable(NotCopiableNotMovable&&) = delete;
+  NotCopiableNotMovable& operator=(NotCopiableNotMovable&&) = delete;
+};
+
+template <class Mutex> void testInPlaceConstruction() {
+  // This won't compile without construct_in_place
+  folly::Synchronized<NotCopiableNotMovable> a(
+    folly::construct_in_place, 5, "a"
+  );
+}
+
 
 #endif  /* FOLLY_TEST_SYNCHRONIZEDTESTLIB_INL_H */
index 099efe96e6d93c217045e8c229744d0554d2e28e..4313e6e46994bb7ec135f8dfc09ca3065cfae883 100644 (file)
@@ -44,6 +44,8 @@ template <class Mutex> void testTimedSynchronizedWithConst();
 
 template <class Mutex> void testConstCopy();
 
+template <class Mutex> void testInPlaceConstruction();
+
 #include <folly/test/SynchronizedTestLib-inl.h>
 
 #endif /* FOLLY_TEST_SYNCHRONIZEDTESTLIB_H */