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) ...@@ -840,6 +840,7 @@ if (BUILD_TESTS)
SOURCES ProducerConsumerQueueTest.cpp SOURCES ProducerConsumerQueueTest.cpp
TEST random_test SOURCES RandomTest.cpp TEST random_test SOURCES RandomTest.cpp
TEST range_test SOURCES RangeTest.cpp TEST range_test SOURCES RangeTest.cpp
TEST replaceable_test SOURCES ReplaceableTest.cpp
TEST scope_guard_test SOURCES ScopeGuardTest.cpp TEST scope_guard_test SOURCES ScopeGuardTest.cpp
# Heavily dependent on drand and srand48 # Heavily dependent on drand and srand48
#TEST shared_mutex_test SOURCES SharedMutexTest.cpp #TEST shared_mutex_test SOURCES SharedMutexTest.cpp
......
...@@ -595,11 +595,8 @@ class alignas(T) Replaceable ...@@ -595,11 +595,8 @@ class alignas(T) Replaceable
/** /**
* `swap` just calls `swap(T&, T&)`. * `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; using std::swap;
swap(*(*this), *other); swap(*(*this), *other);
} }
......
...@@ -44,7 +44,9 @@ struct HasRef final { ...@@ -44,7 +44,9 @@ struct HasRef final {
++i1; ++i1;
} }
}; };
void swap(HasRef& lhs, HasRef& rhs) noexcept(false) {
std::swap(lhs.i1, rhs.i1);
}
struct OddA; struct OddA;
struct OddB { struct OddB {
OddB() = delete; OddB() = delete;
...@@ -70,6 +72,11 @@ struct OddA { ...@@ -70,6 +72,11 @@ struct OddA {
struct Indestructible { struct Indestructible {
~Indestructible() = delete; ~Indestructible() = delete;
}; };
struct HasInt {
explicit HasInt(int v) : value{v} {}
int value{};
};
} // namespace } // namespace
template <typename T> template <typename T>
...@@ -289,3 +296,41 @@ TEST(ReplaceableTest, Conversions) { ...@@ -289,3 +296,41 @@ TEST(ReplaceableTest, Conversions) {
Replaceable<OddA> rOddA{std::move(rOddB)}; Replaceable<OddA> rOddA{std::move(rOddB)};
Replaceable<OddB> rOddB2{rOddA}; 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