mirror of
https://github.com/abseil/abseil-cpp.git
synced 2026-06-04 12:07:05 +08:00
Update absl::make_unique to reflect the C++14 minimum
absl::make_unique is now std::make_unique in all configurations. Documentation has been updated to recommend using the std::make_unique spelling. PiperOrigin-RevId: 488988005 Change-Id: Iddb8b863e6301876713d78c3fbe6660d0f9a38cf
This commit is contained in:
committed by
Copybara-Service
parent
4b48854949
commit
ae52431653
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
@@ -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));
|
||||
|
||||
Reference in New Issue
Block a user