From ea0e750e52ee223db34a242f9a7229ac04a0f473 Mon Sep 17 00:00:00 2001 From: Abseil Team Date: Wed, 25 Apr 2018 10:38:08 -0700 Subject: - 2f6a3c92ce0f64e0923ad326ec5d07eae03061fd Add C++14's std::exchange to absl/utility/utility.h. by Abseil Team - 9f2c9adbf998dd9062c8cc3da1076bde87081d71 Fix comment typo. by Greg Falcon GitOrigin-RevId: 2f6a3c92ce0f64e0923ad326ec5d07eae03061fd Change-Id: I7b9db94ad315092baefe56b02f250acadafbe312 --- absl/debugging/symbolize_win32.inc | 2 +- absl/utility/utility.h | 22 ++++++++++++++++++++++ absl/utility/utility_test.cc | 8 ++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/absl/debugging/symbolize_win32.inc b/absl/debugging/symbolize_win32.inc index c300c50a..e3fff74d 100644 --- a/absl/debugging/symbolize_win32.inc +++ b/absl/debugging/symbolize_win32.inc @@ -40,7 +40,7 @@ void InitializeSymbolizer(const char *argv0) { SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME); if (!SymInitialize(process, nullptr, true)) { // GetLastError() returns a Win32 DWORD, but we assign to - // unsigned long to simplify the ABSL_RAW_LOG case below. The uniform + // unsigned long long to simplify the ABSL_RAW_LOG case below. The uniform // initialization guarantees this is not a narrowing conversion. const unsigned long long error{GetLastError()}; // NOLINT(runtime/int) ABSL_RAW_LOG(FATAL, "SymInitialize() failed: %llu", error); diff --git a/absl/utility/utility.h b/absl/utility/utility.h index 5b9b84e0..d73602c4 100644 --- a/absl/utility/utility.h +++ b/absl/utility/utility.h @@ -24,6 +24,7 @@ // * make_index_sequence == std::make_index_sequence // * index_sequence_for == std::index_sequence_for // * apply == std::apply +// * exchange == std::exchange // // This header file also provides the tag types `in_place_t`, `in_place_type_t`, // and `in_place_index_t`, as well as the constant `in_place`, and @@ -264,6 +265,27 @@ auto apply(Functor&& functor, Tuple&& t) absl::make_index_sequence::type>::value>{}); } + +// exchange +// +// Replaces the value of `obj` with `new_value` and returns the old value of +// `obj`. `absl::exchange` is designed to be a drop-in replacement for C++14's +// `std::exchange`. +// +// Example: +// +// Foo& operator=(Foo&& other) { +// ptr1_ = absl::exchange(other.ptr1_, nullptr); +// int1_ = absl::exchange(other.int1_, -1); +// return *this; +// } +template +T exchange(T& obj, U&& new_value) { + T old_value = absl::move(obj); + obj = absl::forward(new_value); + return old_value; +} + } // namespace absl #endif // ABSL_UTILITY_UTILITY_H_ diff --git a/absl/utility/utility_test.cc b/absl/utility/utility_test.cc index 342165ed..3c447b20 100644 --- a/absl/utility/utility_test.cc +++ b/absl/utility/utility_test.cc @@ -333,5 +333,13 @@ TEST(ApplyTest, FlipFlop) { EXPECT_EQ(42, absl::apply(&FlipFlop::member, std::make_tuple(obj))); } +TEST(ExchangeTest, MoveOnly) { + auto a = Factory(1); + EXPECT_EQ(1, *a); + auto b = absl::exchange(a, Factory(2)); + EXPECT_EQ(2, *a); + EXPECT_EQ(1, *b); +} + } // namespace -- cgit v1.2.3