//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// template<class T, class Alloc, class... Args>
// constexpr T uninitialized_construct_using_allocator(const Alloc& alloc, Args&&... args);
// UNSUPPORTED: c++03, c++11, c++14, c++17
// test_memory_resource requires RTTI for dynamic_cast
// UNSUPPORTED: no-rtti
#include <concepts>
#include <memory>
#include <tuple>
#include <utility>
#include "common.h"
#include "test_allocator.h"
constexpr bool test() {
Alloc a(12);
{
auto* ptr = std::allocator<UsesAllocArgT>{}.allocate(1);
std::same_as<UsesAllocArgT*> auto ret = std::uninitialized_construct_using_allocator(ptr, a);
assert(ret == ptr);
assert(ret->allocator_constructed_);
assert(&ret->alloc_ == &a);
std::allocator<UsesAllocArgT>{}.deallocate(ptr, 1);
}
{
auto* ptr = std::allocator<UsesAllocLast>{}.allocate(1);
std::same_as<UsesAllocLast*> auto ret = std::uninitialized_construct_using_allocator(ptr, a);
assert(ret->allocator_constructed_);
assert(&ret->alloc_ == &a);
std::allocator<UsesAllocLast>{}.deallocate(ptr, 1);
}
{
auto* ptr = std::allocator<NotAllocatorAware>{}.allocate(1);
std::same_as<NotAllocatorAware*> auto ret = std::uninitialized_construct_using_allocator(ptr, a);
assert(!ret->allocator_constructed_);
std::allocator<NotAllocatorAware>{}.deallocate(ptr, 1);
}
{
auto* ptr = std::allocator<std::pair<UsesAllocArgT, UsesAllocLast>>{}.allocate(1);
std::same_as<std::pair<UsesAllocArgT, UsesAllocLast>*> auto ret =
std::uninitialized_construct_using_allocator(ptr, a, std::piecewise_construct, std::tuple<>{}, std::tuple<>{});
assert(ret->first.allocator_constructed_);
assert(&ret->first.alloc_ == &a);
assert(ret->second.allocator_constructed_);
assert(&ret->second.alloc_ == &a);
std::allocator<std::pair<UsesAllocArgT, UsesAllocLast>>{}.deallocate(ptr, 1);
}
{
auto* ptr = std::allocator<std::pair<UsesAllocArgT, UsesAllocLast>>{}.allocate(1);
std::same_as<std::pair<UsesAllocArgT, UsesAllocLast>*> auto ret =
std::uninitialized_construct_using_allocator(ptr, a);
assert(ret->first.allocator_constructed_);
assert(&ret->first.alloc_ == &a);
assert(ret->second.allocator_constructed_);
assert(&ret->second.alloc_ == &a);
std::allocator<std::pair<UsesAllocArgT, UsesAllocLast>>{}.deallocate(ptr, 1);
}
{
int val = 0;
auto* ptr = std::allocator<std::pair<UsesAllocArgT, UsesAllocLast>>{}.allocate(1);
std::same_as<std::pair<UsesAllocArgT, UsesAllocLast>*> auto ret =
std::uninitialized_construct_using_allocator(ptr, a, val, val);
assert(ret->first.allocator_constructed_);
assert(&ret->first.alloc_ == &a);
assert(ret->first.ref_type_ == RefType::LValue);
assert(ret->first.val_ptr_ == &val);
assert(ret->second.allocator_constructed_);
assert(&ret->second.alloc_ == &a);
assert(ret->second.ref_type_ == RefType::LValue);
assert(ret->second.val_ptr_ == &val);
std::allocator<std::pair<UsesAllocArgT, UsesAllocLast>>{}.deallocate(ptr, 1);
}
{
int val = 0;
auto* ptr = std::allocator<std::pair<UsesAllocArgT, UsesAllocLast>>{}.allocate(1);
std::same_as<std::pair<UsesAllocArgT, UsesAllocLast>*> auto ret =
std::uninitialized_construct_using_allocator(ptr, a, std::move(val), std::move(val));
assert(ret->first.allocator_constructed_);
assert(&ret->first.alloc_ == &a);
assert(ret->first.ref_type_ == RefType::RValue);
assert(ret->first.val_ptr_ == &val);
assert(ret->second.allocator_constructed_);
assert(&ret->second.alloc_ == &a);
assert(ret->second.ref_type_ == RefType::RValue);
assert(ret->second.val_ptr_ == &val);
std::allocator<std::pair<UsesAllocArgT, UsesAllocLast>>{}.deallocate(ptr, 1);
}
#if TEST_STD_VER >= 23
{
std::pair p{0, 0};
auto* ptr = std::allocator<std::pair<UsesAllocArgT, UsesAllocLast>>{}.allocate(1);
std::same_as<std::pair<UsesAllocArgT, UsesAllocLast>*> auto ret =
std::uninitialized_construct_using_allocator(ptr, a, p);
assert(ret->first.allocator_constructed_);
assert(&ret->first.alloc_ == &a);
assert(ret->first.ref_type_ == RefType::LValue);
assert(ret->first.val_ptr_ == &p.first);
assert(ret->second.allocator_constructed_);
assert(&ret->second.alloc_ == &a);
assert(ret->second.ref_type_ == RefType::LValue);
assert(ret->second.val_ptr_ == &p.second);
std::allocator<std::pair<UsesAllocArgT, UsesAllocLast>>{}.deallocate(ptr, 1);
}
#endif
{
std::pair p{0, 0};
auto* ptr = std::allocator<std::pair<UsesAllocArgT, UsesAllocLast>>{}.allocate(1);
std::same_as<std::pair<UsesAllocArgT, UsesAllocLast>*> auto ret =
std::uninitialized_construct_using_allocator(ptr, a, std::as_const(p));
assert(ret->first.allocator_constructed_);
assert(&ret->first.alloc_ == &a);
assert(ret->first.ref_type_ == RefType::ConstLValue);
assert(ret->first.val_ptr_ == &p.first);
assert(ret->second.allocator_constructed_);
assert(&ret->second.alloc_ == &a);
assert(ret->second.ref_type_ == RefType::ConstLValue);
assert(ret->second.val_ptr_ == &p.second);
std::allocator<std::pair<UsesAllocArgT, UsesAllocLast>>{}.deallocate(ptr, 1);
}
{
std::pair p{0, 0};
auto* ptr = std::allocator<std::pair<UsesAllocArgT, UsesAllocLast>>{}.allocate(1);
std::same_as<std::pair<UsesAllocArgT, UsesAllocLast>*> auto ret =
std::uninitialized_construct_using_allocator(ptr, a, std::move(p));
assert(ret->first.allocator_constructed_);
assert(&ret->first.alloc_ == &a);
assert(ret->first.ref_type_ == RefType::RValue);
assert(ret->first.val_ptr_ == &p.first);
assert(ret->second.allocator_constructed_);
assert(&ret->second.alloc_ == &a);
assert(ret->second.ref_type_ == RefType::RValue);
assert(ret->second.val_ptr_ == &p.second);
std::allocator<std::pair<UsesAllocArgT, UsesAllocLast>>{}.deallocate(ptr, 1);
}
#if TEST_STD_VER >= 23
{
std::pair p{0, 0};
auto* ptr = std::allocator<std::pair<UsesAllocArgT, UsesAllocLast>>{}.allocate(1);
std::same_as<std::pair<UsesAllocArgT, UsesAllocLast>*> auto ret =
std::uninitialized_construct_using_allocator(ptr, a, std::move(std::as_const(p)));
assert(ret->first.allocator_constructed_);
assert(&ret->first.alloc_ == &a);
assert(ret->first.ref_type_ == RefType::ConstRValue);
assert(ret->first.val_ptr_ == &p.first);
assert(ret->second.allocator_constructed_);
assert(&ret->second.alloc_ == &a);
assert(ret->second.ref_type_ == RefType::ConstRValue);
assert(ret->second.val_ptr_ == &p.second);
std::allocator<std::pair<UsesAllocArgT, UsesAllocLast>>{}.deallocate(ptr, 1);
}
#endif
{
ConvertibleToPair ctp;
auto* ptr = std::allocator<std::pair<int, int>>{}.allocate(1);
std::same_as<std::pair<int, int>*> auto ret = std::uninitialized_construct_using_allocator(ptr, a, ctp);
assert(ret == ptr);
assert(ret->first == 1);
assert(ret->second == 2);
std::allocator<std::pair<int, int>>{}.deallocate(ptr, 1);
}
{
ConvertibleToPair ctp;
auto* ptr = std::allocator<std::pair<int, int>>{}.allocate(1);
std::same_as<std::pair<int, int>*> auto ret = std::uninitialized_construct_using_allocator(ptr, a, std::move(ctp));
assert(ret == ptr);
assert(ret->first == 1);
assert(ret->second == 2);
std::allocator<std::pair<int, int>>{}.deallocate(ptr, 1);
}
return true;
}
int main(int, char**) {
test();
static_assert(test());
}