//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03, c++11, c++14, c++17
// template<class T>
// constexpr unique_ptr<T> make_unique_for_overwrite(); // T is not array
//
// template<class T>
// constexpr unique_ptr<T> make_unique_for_overwrite(size_t n); // T is U[]
//
// template<class T, class... Args>
// unspecified make_unique_for_overwrite(Args&&...) = delete; // T is U[N]
#include <cassert>
#include <concepts>
#include <cstring>
#include <memory>
#include <utility>
#include "test_macros.h"
template <class T, class... Args>
concept HasMakeUniqueForOverwrite =
requires(Args&&... args) { std::make_unique_for_overwrite<T>(std::forward<Args>(args)...); };
struct Foo {
int i;
};
// template<class T>
// constexpr unique_ptr<T> make_unique_for_overwrite();
static_assert(HasMakeUniqueForOverwrite<int>);
static_assert(HasMakeUniqueForOverwrite<Foo>);
static_assert(!HasMakeUniqueForOverwrite<int, int>);
static_assert(!HasMakeUniqueForOverwrite<Foo, Foo>);
// template<class T>
// constexpr unique_ptr<T> make_unique_for_overwrite(size_t n);
static_assert(HasMakeUniqueForOverwrite<int[], std::size_t>);
static_assert(HasMakeUniqueForOverwrite<Foo[], std::size_t>);
static_assert(!HasMakeUniqueForOverwrite<int[]>);
static_assert(!HasMakeUniqueForOverwrite<Foo[]>);
static_assert(!HasMakeUniqueForOverwrite<int[], std::size_t, int>);
static_assert(!HasMakeUniqueForOverwrite<Foo[], std::size_t, int>);
// template<class T, class... Args>
// unspecified make_unique_for_overwrite(Args&&...) = delete;
static_assert(!HasMakeUniqueForOverwrite<int[2]>);
static_assert(!HasMakeUniqueForOverwrite<int[2], std::size_t>);
static_assert(!HasMakeUniqueForOverwrite<int[2], int>);
static_assert(!HasMakeUniqueForOverwrite<int[2], int, int>);
static_assert(!HasMakeUniqueForOverwrite<Foo[2]>);
static_assert(!HasMakeUniqueForOverwrite<Foo[2], std::size_t>);
static_assert(!HasMakeUniqueForOverwrite<Foo[2], int>);
static_assert(!HasMakeUniqueForOverwrite<Foo[2], int, int>);
struct WithDefaultConstructor {
int i;
constexpr WithDefaultConstructor() : i(5) {}
};
TEST_CONSTEXPR_CXX23 bool test() {
// single int
{
std::same_as<std::unique_ptr<int>> decltype(auto) ptr = std::make_unique_for_overwrite<int>();
// memory is available for write, otherwise constexpr test would fail
*ptr = 5;
}
// unbounded array int[]
{
std::same_as<std::unique_ptr<int[]>> decltype(auto) ptrs = std::make_unique_for_overwrite<int[]>(3);
// memory is available for write, otherwise constexpr test would fail
ptrs[0] = 3;
ptrs[1] = 4;
ptrs[2] = 5;
}
// single with default constructor
{
std::same_as<std::unique_ptr<WithDefaultConstructor>> decltype(auto) ptr =
std::make_unique_for_overwrite<WithDefaultConstructor>();
assert(ptr->i == 5);
}
// unbounded array with default constructor
{
std::same_as<std::unique_ptr<WithDefaultConstructor[]>> decltype(auto) ptrs =
std::make_unique_for_overwrite<WithDefaultConstructor[]>(3);
assert(ptrs[0].i == 5);
assert(ptrs[1].i == 5);
assert(ptrs[2].i == 5);
}
return true;
}
// The standard specifically says to use `new (p) T`, which means that we should pick up any
// custom in-class operator new if there is one.
struct WithCustomNew {
inline static bool customNewCalled = false;
inline static bool customNewArrCalled = false;
static void* operator new(std::size_t n) {
customNewCalled = true;
return ::operator new(n);
;
}
static void* operator new[](std::size_t n) {
customNewArrCalled = true;
return ::operator new[](n);
}
};
void testCustomNew() {
// single with custom operator new
{
[[maybe_unused]] std::same_as<std::unique_ptr<WithCustomNew>> decltype(auto) ptr =
std::make_unique_for_overwrite<WithCustomNew>();
assert(WithCustomNew::customNewCalled);
}
// unbounded array with custom operator new
{
[[maybe_unused]] std::same_as<std::unique_ptr<WithCustomNew[]>> decltype(auto) ptr =
std::make_unique_for_overwrite<WithCustomNew[]>(3);
assert(WithCustomNew::customNewArrCalled);
}
}
int main(int, char**) {
test();
testCustomNew();
#if TEST_STD_VER >= 23
static_assert(test());
#endif
return 0;
}