diff options
-rw-r--r-- | absl/memory/BUILD.bazel | 15 | ||||
-rw-r--r-- | absl/memory/CMakeLists.txt | 14 | ||||
-rw-r--r-- | absl/memory/memory.h | 102 | ||||
-rw-r--r-- | absl/memory/memory_exception_safety_test.cc | 57 | ||||
-rw-r--r-- | absl/memory/memory_test.cc | 98 |
5 files changed, 6 insertions, 280 deletions
diff --git a/absl/memory/BUILD.bazel b/absl/memory/BUILD.bazel index 389aedf3..a93f54a6 100644 --- a/absl/memory/BUILD.bazel +++ b/absl/memory/BUILD.bazel @@ -50,18 +50,3 @@ cc_test( "@com_google_googletest//:gtest_main", ], ) - -cc_test( - name = "memory_exception_safety_test", - srcs = [ - "memory_exception_safety_test.cc", - ], - copts = ABSL_TEST_COPTS, - linkopts = ABSL_DEFAULT_LINKOPTS, - deps = [ - ":memory", - "//absl/base:config", - "//absl/base:exception_safety_testing", - "@com_google_googletest//:gtest_main", - ], -) diff --git a/absl/memory/CMakeLists.txt b/absl/memory/CMakeLists.txt index 9d50e1dc..c5ed4b42 100644 --- a/absl/memory/CMakeLists.txt +++ b/absl/memory/CMakeLists.txt @@ -39,17 +39,3 @@ absl_cc_test( absl::core_headers GTest::gmock_main ) - -absl_cc_test( - NAME - memory_exception_safety_test - SRCS - "memory_exception_safety_test.cc" - COPTS - ${ABSL_TEST_COPTS} - DEPS - absl::memory - absl::config - absl::exception_safety_testing - GTest::gmock_main -) diff --git a/absl/memory/memory.h b/absl/memory/memory.h index d6332606..e5ff0e65 100644 --- a/absl/memory/memory.h +++ b/absl/memory/memory.h @@ -75,32 +75,6 @@ std::unique_ptr<T> WrapUnique(T* ptr) { return std::unique_ptr<T>(ptr); } -namespace memory_internal { - -// Traits to select proper overload and return type for `absl::make_unique<>`. -template <typename T> -struct MakeUniqueResult { - using scalar = std::unique_ptr<T>; -}; -template <typename T> -struct MakeUniqueResult<T[]> { - using array = std::unique_ptr<T[]>; -}; -template <typename T, size_t N> -struct MakeUniqueResult<T[N]> { - using invalid = void; -}; - -} // namespace memory_internal - -// gcc 4.8 has __cplusplus at 201301 but the libstdc++ shipped with it doesn't -// define make_unique. Other supported compilers either just define __cplusplus -// as 201103 but have make_unique (msvc), or have make_unique whenever -// __cplusplus > 201103 (clang). -#if (__cplusplus > 201103L || defined(_MSC_VER)) && \ - !(defined(__GLIBCXX__) && !defined(__cpp_lib_make_unique)) -using std::make_unique; -#else // ----------------------------------------------------------------------------- // Function Template: make_unique<T>() // ----------------------------------------------------------------------------- @@ -109,82 +83,18 @@ using std::make_unique; // during the construction process. `absl::make_unique<>` also avoids redundant // type declarations, by avoiding the need to explicitly use the `new` operator. // -// This implementation of `absl::make_unique<>` is designed for C++11 code and -// will be replaced in C++14 by the equivalent `std::make_unique<>` abstraction. -// `absl::make_unique<>` is designed to be 100% compatible with -// `std::make_unique<>` so that the eventual migration will involve a simple -// rename operation. +// https://en.cppreference.com/w/cpp/memory/unique_ptr/make_unique // // For more background on why `std::unique_ptr<T>(new T(a,b))` is problematic, // see Herb Sutter's explanation on // (Exception-Safe Function Calls)[https://herbsutter.com/gotw/_102/]. // (In general, reviewers should treat `new T(a,b)` with scrutiny.) // -// Example usage: -// -// auto p = make_unique<X>(args...); // 'p' is a std::unique_ptr<X> -// auto pa = make_unique<X[]>(5); // 'pa' is a std::unique_ptr<X[]> -// -// Three overloads of `absl::make_unique` are required: -// -// - For non-array T: -// -// Allocates a T with `new T(std::forward<Args> args...)`, -// forwarding all `args` to T's constructor. -// Returns a `std::unique_ptr<T>` owning that object. -// -// - For an array of unknown bounds T[]: -// -// `absl::make_unique<>` will allocate an array T of type U[] with -// `new U[n]()` and return a `std::unique_ptr<U[]>` owning that array. -// -// Note that 'U[n]()' is different from 'U[n]', and elements will be -// value-initialized. Note as well that `std::unique_ptr` will perform its -// own destruction of the array elements upon leaving scope, even though -// the array [] does not have a default destructor. -// -// NOTE: an array of unknown bounds T[] may still be (and often will be) -// initialized to have a size, and will still use this overload. E.g: -// -// auto my_array = absl::make_unique<int[]>(10); -// -// - For an array of known bounds T[N]: -// -// `absl::make_unique<>` is deleted (like with `std::make_unique<>`) as -// this overload is not useful. -// -// NOTE: an array of known bounds T[N] is not considered a useful -// construction, and may cause undefined behavior in templates. E.g: -// -// auto my_array = absl::make_unique<int[10]>(); -// -// In those cases, of course, you can still use the overload above and -// simply initialize it to its desired size: -// -// auto my_array = absl::make_unique<int[]>(10); - -// `absl::make_unique` overload for non-array types. -template <typename T, typename... Args> -typename memory_internal::MakeUniqueResult<T>::scalar make_unique( - Args&&... args) { - return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); -} - -// `absl::make_unique` overload for an array T[] of unknown bounds. -// The array allocation needs to use the `new T[size]` form and cannot take -// element constructor arguments. The `std::unique_ptr` will manage destructing -// these array elements. -template <typename T> -typename memory_internal::MakeUniqueResult<T>::array make_unique(size_t n) { - return std::unique_ptr<T>(new typename absl::remove_extent_t<T>[n]()); -} - -// `absl::make_unique` overload for an array T[N] of known bounds. -// This construction will be rejected. -template <typename T, typename... Args> -typename memory_internal::MakeUniqueResult<T>::invalid make_unique( - Args&&... /* args */) = delete; -#endif +// Historical note: Abseil once provided a C++11 compatible implementation of +// the C++14's `std::make_unique`. Now that C++11 support has been sunsetted, +// `absl::make_unique` simply uses the STL-provided implementation. New code +// should use `std::make_unique`. +using std::make_unique; // ----------------------------------------------------------------------------- // Function Template: RawPtr() diff --git a/absl/memory/memory_exception_safety_test.cc b/absl/memory/memory_exception_safety_test.cc deleted file mode 100644 index 1df72614..00000000 --- a/absl/memory/memory_exception_safety_test.cc +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2018 The Abseil Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "absl/memory/memory.h" - -#include "absl/base/config.h" - -#ifdef ABSL_HAVE_EXCEPTIONS - -#include "gtest/gtest.h" -#include "absl/base/internal/exception_safety_testing.h" - -namespace absl { -ABSL_NAMESPACE_BEGIN -namespace { - -constexpr int kLength = 50; -using Thrower = testing::ThrowingValue<testing::TypeSpec::kEverythingThrows>; - -TEST(MakeUnique, CheckForLeaks) { - constexpr int kValue = 321; - auto tester = testing::MakeExceptionSafetyTester() - .WithInitialValue(Thrower(kValue)) - // Ensures make_unique does not modify the input. The real - // test, though, is ConstructorTracker checking for leaks. - .WithContracts(testing::strong_guarantee); - - EXPECT_TRUE(tester.Test([](Thrower* thrower) { - static_cast<void>(absl::make_unique<Thrower>(*thrower)); - })); - - EXPECT_TRUE(tester.Test([](Thrower* thrower) { - static_cast<void>(absl::make_unique<Thrower>(std::move(*thrower))); - })); - - // Test T[n] overload - EXPECT_TRUE(tester.Test([&](Thrower*) { - static_cast<void>(absl::make_unique<Thrower[]>(kLength)); - })); -} - -} // namespace -ABSL_NAMESPACE_END -} // namespace absl - -#endif // ABSL_HAVE_EXCEPTIONS diff --git a/absl/memory/memory_test.cc b/absl/memory/memory_test.cc index 14b8b982..6f01cdff 100644 --- a/absl/memory/memory_test.cc +++ b/absl/memory/memory_test.cc @@ -64,13 +64,6 @@ TEST(WrapUniqueTest, WrapUnique) { EXPECT_EQ(0, DestructorVerifier::instance_count()); } -TEST(MakeUniqueTest, Basic) { - std::unique_ptr<std::string> p = absl::make_unique<std::string>(); - EXPECT_EQ("", *p); - p = absl::make_unique<std::string>("hi"); - EXPECT_EQ("hi", *p); -} - // InitializationVerifier fills in a pattern when allocated so we can // distinguish between its default and value initialized states (without // accessing truly uninitialized memory). @@ -94,65 +87,6 @@ struct InitializationVerifier { int b; }; -TEST(Initialization, MakeUnique) { - auto p = absl::make_unique<InitializationVerifier>(); - - EXPECT_EQ(0, p->a); - EXPECT_EQ(0, p->b); -} - -TEST(Initialization, MakeUniqueArray) { - auto p = absl::make_unique<InitializationVerifier[]>(2); - - EXPECT_EQ(0, p[0].a); - EXPECT_EQ(0, p[0].b); - EXPECT_EQ(0, p[1].a); - EXPECT_EQ(0, p[1].b); -} - -struct MoveOnly { - MoveOnly() = default; - explicit MoveOnly(int i1) : ip1{new int{i1}} {} - MoveOnly(int i1, int i2) : ip1{new int{i1}}, ip2{new int{i2}} {} - std::unique_ptr<int> ip1; - std::unique_ptr<int> ip2; -}; - -struct AcceptMoveOnly { - explicit AcceptMoveOnly(MoveOnly m) : m_(std::move(m)) {} - MoveOnly m_; -}; - -TEST(MakeUniqueTest, MoveOnlyTypeAndValue) { - using ExpectedType = std::unique_ptr<MoveOnly>; - { - auto p = absl::make_unique<MoveOnly>(); - static_assert(std::is_same<decltype(p), ExpectedType>::value, - "unexpected return type"); - EXPECT_TRUE(!p->ip1); - EXPECT_TRUE(!p->ip2); - } - { - auto p = absl::make_unique<MoveOnly>(1); - static_assert(std::is_same<decltype(p), ExpectedType>::value, - "unexpected return type"); - EXPECT_TRUE(p->ip1 && *p->ip1 == 1); - EXPECT_TRUE(!p->ip2); - } - { - auto p = absl::make_unique<MoveOnly>(1, 2); - static_assert(std::is_same<decltype(p), ExpectedType>::value, - "unexpected return type"); - EXPECT_TRUE(p->ip1 && *p->ip1 == 1); - EXPECT_TRUE(p->ip2 && *p->ip2 == 2); - } -} - -TEST(MakeUniqueTest, AcceptMoveOnly) { - auto p = absl::make_unique<AcceptMoveOnly>(MoveOnly()); - p = std::unique_ptr<AcceptMoveOnly>(new AcceptMoveOnly(MoveOnly())); -} - struct ArrayWatch { void* operator new[](size_t n) { allocs().push_back(n); @@ -165,38 +99,6 @@ struct ArrayWatch { } }; -TEST(MakeUniqueTest, Array) { - // Ensure state is clean before we start so that these tests - // are order-agnostic. - ArrayWatch::allocs().clear(); - - auto p = absl::make_unique<ArrayWatch[]>(5); - static_assert(std::is_same<decltype(p), std::unique_ptr<ArrayWatch[]>>::value, - "unexpected return type"); - EXPECT_THAT(ArrayWatch::allocs(), ElementsAre(5 * sizeof(ArrayWatch))); -} - -TEST(MakeUniqueTest, NotAmbiguousWithStdMakeUnique) { - // Ensure that absl::make_unique is not ambiguous with std::make_unique. - // In C++14 mode, the below call to make_unique has both types as candidates. - struct TakesStdType { - explicit TakesStdType(const std::vector<int>& vec) {} - }; - using absl::make_unique; - (void)make_unique<TakesStdType>(std::vector<int>()); -} - -#if 0 -// These tests shouldn't compile. -TEST(MakeUniqueTestNC, AcceptMoveOnlyLvalue) { - auto m = MoveOnly(); - auto p = absl::make_unique<AcceptMoveOnly>(m); -} -TEST(MakeUniqueTestNC, KnownBoundArray) { - auto p = absl::make_unique<ArrayWatch[5]>(); -} -#endif - TEST(RawPtrTest, RawPointer) { int i = 5; EXPECT_EQ(&i, absl::RawPtr(&i)); |