Commit 74f41a0b authored by Joe Loser's avatar Joe Loser Committed by Facebook Github Bot

Mark swap(Replaceable) conditionally noexcept (#1070)

Summary:
- Mark `swap(Replaceable&)` noexcept iff `Replaceable` is
  noexcept-swappable. As the comment aludes to, this is a C++17 feature,
  but we have it backported in `folly/Traits.h`
Pull Request resolved: https://github.com/facebook/folly/pull/1070

Reviewed By: LeeHowes

Differential Revision: D14518839

Pulled By: yfeldblum

fbshipit-source-id: 966cca1733cf2a397c2406577baf941992f362d6
parent 28efb04f
......@@ -840,6 +840,7 @@ if (BUILD_TESTS)
SOURCES ProducerConsumerQueueTest.cpp
TEST random_test SOURCES RandomTest.cpp
TEST range_test SOURCES RangeTest.cpp
TEST replaceable_test SOURCES ReplaceableTest.cpp
TEST scope_guard_test SOURCES ScopeGuardTest.cpp
# Heavily dependent on drand and srand48
#TEST shared_mutex_test SOURCES SharedMutexTest.cpp
......
......@@ -595,11 +595,8 @@ class alignas(T) Replaceable
/**
* `swap` just calls `swap(T&, T&)`.
*
* Should be `noexcept(std::is_nothrow_swappable<T>::value)` but we don't
* depend on C++17 features.
*/
void swap(Replaceable& other) {
void swap(Replaceable& other) noexcept(IsNothrowSwappable<Replaceable>{}) {
using std::swap;
swap(*(*this), *other);
}
......
......@@ -44,7 +44,9 @@ struct HasRef final {
++i1;
}
};
void swap(HasRef& lhs, HasRef& rhs) noexcept(false) {
std::swap(lhs.i1, rhs.i1);
}
struct OddA;
struct OddB {
OddB() = delete;
......@@ -70,6 +72,11 @@ struct OddA {
struct Indestructible {
~Indestructible() = delete;
};
struct HasInt {
explicit HasInt(int v) : value{v} {}
int value{};
};
} // namespace
template <typename T>
......@@ -289,3 +296,41 @@ TEST(ReplaceableTest, Conversions) {
Replaceable<OddA> rOddA{std::move(rOddB)};
Replaceable<OddB> rOddB2{rOddA};
}
TEST(ReplaceableTest, swapMemberFunctionIsNoexcept) {
int v1{1};
int v2{2};
auto r1 = Replaceable<HasInt>{v1};
auto r2 = Replaceable<HasInt>{v2};
EXPECT_TRUE(noexcept(r1.swap(r2)));
r1.swap(r2);
EXPECT_EQ(v2, r1->value);
EXPECT_EQ(v1, r2->value);
}
TEST(ReplaceableTest, swapMemberFunctionIsNotNoexcept) {
int v1{1};
int v2{2};
auto r1 = Replaceable<HasRef>{v1};
auto r2 = Replaceable<HasRef>{v2};
EXPECT_FALSE(noexcept(r1.swap(r2)));
r1.swap(r2);
EXPECT_EQ(v1, r1->i1);
EXPECT_EQ(v2, r2->i1);
}
namespace adl_test {
struct UserDefinedSwap {
bool calledSwap{};
};
void swap(UserDefinedSwap& lhs, UserDefinedSwap&) noexcept(false) {
lhs.calledSwap = true;
}
} // namespace adl_test
TEST(ReplaceableTest, swapMemberFunctionDelegatesToUserSwap) {
auto r1 = Replaceable<adl_test::UserDefinedSwap>{};
auto r2 = Replaceable<adl_test::UserDefinedSwap>{};
r1.swap(r2);
EXPECT_TRUE(r1->calledSwap);
}
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