Commit 7c4e381e authored by Alexey Spiridonov's avatar Alexey Spiridonov Committed by facebook-github-bot-9

Add a tag type for in-place construction

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
parent a93b1f39
...@@ -282,6 +282,14 @@ struct Synchronized { ...@@ -282,6 +282,14 @@ struct Synchronized {
explicit Synchronized(T&& rhs) noexcept(nxMoveCtor) explicit Synchronized(T&& rhs) noexcept(nxMoveCtor)
: datum_(std::move(rhs)) {} : 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 * The canonical assignment operator only assigns the data, NOT the
* mutex. It locks the two objects in ascending order of their * mutex. It locks the two objects in ascending order of their
......
...@@ -377,6 +377,13 @@ bool greater_than(LHS const lhs) { ...@@ -377,6 +377,13 @@ bool greater_than(LHS const lhs) {
>(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 } // namespace folly
FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(std::basic_string); FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(std::basic_string);
......
...@@ -117,4 +117,8 @@ TYPED_TEST(SynchronizedTimedWithConstTest, TimedSynchronizeWithConst) { ...@@ -117,4 +117,8 @@ TYPED_TEST(SynchronizedTimedWithConstTest, TimedSynchronizeWithConst) {
testTimedSynchronizedWithConst<TypeParam>(); testTimedSynchronizedWithConst<TypeParam>();
} }
TYPED_TEST(SynchronizedTest, InPlaceConstruction) {
testInPlaceConstruction<TypeParam>();
}
} }
...@@ -339,5 +339,20 @@ template <class Mutex> void testConstCopy() { ...@@ -339,5 +339,20 @@ template <class Mutex> void testConstCopy() {
EXPECT_EQ(result, input); 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 */ #endif /* FOLLY_TEST_SYNCHRONIZEDTESTLIB_INL_H */
...@@ -44,6 +44,8 @@ template <class Mutex> void testTimedSynchronizedWithConst(); ...@@ -44,6 +44,8 @@ template <class Mutex> void testTimedSynchronizedWithConst();
template <class Mutex> void testConstCopy(); template <class Mutex> void testConstCopy();
template <class Mutex> void testInPlaceConstruction();
#include <folly/test/SynchronizedTestLib-inl.h> #include <folly/test/SynchronizedTestLib-inl.h>
#endif /* FOLLY_TEST_SYNCHRONIZEDTESTLIB_H */ #endif /* FOLLY_TEST_SYNCHRONIZEDTESTLIB_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment