From efcacd1c99bbea5411507e39ce74051a279be5e7 Mon Sep 17 00:00:00 2001 From: Giuseppe Ottaviano Date: Fri, 23 Jun 2017 15:19:01 -0700 Subject: [PATCH] MoveOnly utility Summary: Same as `boost::noncopyable` but it does not disable move constructor/assignment. Reviewed By: luciang Differential Revision: D5311043 fbshipit-source-id: 44fe95712169b95a00e474385be43fa857cfd8ec --- folly/Utility.h | 25 ++++++++++++++++++++++++- folly/test/UtilityTest.cpp | 24 +++++++++++++++++++++++- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/folly/Utility.h b/folly/Utility.h index 4d6725d7..1d378618 100644 --- a/folly/Utility.h +++ b/folly/Utility.h @@ -158,4 +158,27 @@ struct Identity { return static_cast(x); } }; -} + +namespace moveonly_ { // Protection from unintended ADL. + +/** + * Disallow copy but not move in derived types. This is essentially + * boost::noncopyable (the implementation is almost identical) but it + * doesn't delete move constructor and move assignment. + */ +class MoveOnly { + protected: + constexpr MoveOnly() = default; + ~MoveOnly() = default; + + MoveOnly(MoveOnly&&) = default; + MoveOnly& operator=(MoveOnly&&) = default; + MoveOnly(const MoveOnly&) = delete; + MoveOnly& operator=(const MoveOnly&) = delete; +}; + +} // namespace moveonly_ + +using MoveOnly = moveonly_::MoveOnly; + +} // namespace folly diff --git a/folly/test/UtilityTest.cpp b/folly/test/UtilityTest.cpp index 9b77e170..5507b96f 100644 --- a/folly/test/UtilityTest.cpp +++ b/folly/test/UtilityTest.cpp @@ -14,8 +14,9 @@ * limitations under the License. */ -#include +#include +#include #include namespace { @@ -88,3 +89,24 @@ TEST(FollyIntegerSequence, core) { static_assert(seq3.size() == 3, ""); EXPECT_EQ(3, seq3.size()); } + +TEST_F(UtilityTest, MoveOnly) { + class FooBar : folly::MoveOnly { + int a; + }; + + static_assert( + !std::is_copy_constructible::value, + "Should not be copy constructible"); + + // Test that move actually works. + FooBar foobar; + FooBar foobar2(std::move(foobar)); + (void)foobar2; + + // Test that inheriting from MoveOnly doesn't prevent the move + // constructor from being noexcept. + static_assert( + std::is_nothrow_move_constructible::value, + "Should have noexcept move constructor"); +} -- 2.34.1