From 7c4e381ec6b27e098b1c69f659e10c9ac09c4126 Mon Sep 17 00:00:00 2001 From: Alexey Spiridonov Date: Mon, 9 Nov 2015 11:16:11 -0800 Subject: [PATCH] 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 --- folly/Synchronized.h | 8 ++++++++ folly/Traits.h | 7 +++++++ folly/test/SynchronizedTest.cpp | 4 ++++ folly/test/SynchronizedTestLib-inl.h | 15 +++++++++++++++ folly/test/SynchronizedTestLib.h | 2 ++ 5 files changed, 36 insertions(+) diff --git a/folly/Synchronized.h b/folly/Synchronized.h index dcc5f7dd..8a2f9b95 100644 --- a/folly/Synchronized.h +++ b/folly/Synchronized.h @@ -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 + explicit Synchronized(construct_in_place_t, Args&&... args) + : datum_(std::forward(args)...) {} + /** * The canonical assignment operator only assigns the data, NOT the * mutex. It locks the two objects in ascending order of their diff --git a/folly/Traits.h b/folly/Traits.h index caeb852c..16aab8d6 100644 --- a/folly/Traits.h +++ b/folly/Traits.h @@ -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); diff --git a/folly/test/SynchronizedTest.cpp b/folly/test/SynchronizedTest.cpp index 841f2b25..afd87f91 100644 --- a/folly/test/SynchronizedTest.cpp +++ b/folly/test/SynchronizedTest.cpp @@ -117,4 +117,8 @@ TYPED_TEST(SynchronizedTimedWithConstTest, TimedSynchronizeWithConst) { testTimedSynchronizedWithConst(); } +TYPED_TEST(SynchronizedTest, InPlaceConstruction) { + testInPlaceConstruction(); +} + } diff --git a/folly/test/SynchronizedTestLib-inl.h b/folly/test/SynchronizedTestLib-inl.h index ef4045c8..29c7421c 100644 --- a/folly/test/SynchronizedTestLib-inl.h +++ b/folly/test/SynchronizedTestLib-inl.h @@ -339,5 +339,20 @@ template 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 void testInPlaceConstruction() { + // This won't compile without construct_in_place + folly::Synchronized a( + folly::construct_in_place, 5, "a" + ); +} + #endif /* FOLLY_TEST_SYNCHRONIZEDTESTLIB_INL_H */ diff --git a/folly/test/SynchronizedTestLib.h b/folly/test/SynchronizedTestLib.h index 099efe96..4313e6e4 100644 --- a/folly/test/SynchronizedTestLib.h +++ b/folly/test/SynchronizedTestLib.h @@ -44,6 +44,8 @@ template void testTimedSynchronizedWithConst(); template void testConstCopy(); +template void testInPlaceConstruction(); + #include #endif /* FOLLY_TEST_SYNCHRONIZEDTESTLIB_H */ -- 2.34.1