Commit ae524316 by Derek Mauro Committed by Copybara-Service

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
parent 4b488549
......@@ -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()
......
// 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));
......
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