-------------------------------------------------------------------
``__cpp_lib_adaptor_iterator_pair_constructor`` ``202106L``
------------------------------------------------- -----------------
- ``__cpp_lib_allocate_at_least`` *unimplemented*
+ ``__cpp_lib_allocate_at_least`` ``202106L``
------------------------------------------------- -----------------
``__cpp_lib_associative_heterogeneous_erasure`` *unimplemented*
------------------------------------------------- -----------------
"`P2212R2 <https://wg21.link/P2212R2>`__","LWG","Relax Requirements for time_point::clock","February 2021","",""
"`P2259R1 <https://wg21.link/P2259R1>`__","LWG","Repairing input range adaptors and counted_iterator","February 2021","",""
"","","","","",""
-"`P0401R6 <https://wg21.link/P0401R6>`__","LWG","Providing size feedback in the Allocator interface","June 2021","",""
+"`P0401R6 <https://wg21.link/P0401R6>`__","LWG","Providing size feedback in the Allocator interface","June 2021","|Complete|","15.0"
"`P0448R4 <https://wg21.link/P0448R4>`__","LWG","A strstream replacement using span<charT> as buffer","June 2021","",""
"`P1132R8 <https://wg21.link/P1132R8>`__","LWG","out_ptr - a scalable output pointer abstraction","June 2021","",""
"`P1328R1 <https://wg21.link/P1328R1>`__","LWG","Making std::type_info::operator== constexpr","June 2021","",""
__locale
__mbstate_t.h
__memory/addressof.h
+ __memory/allocate_at_least.h
__memory/allocation_guard.h
__memory/allocator.h
__memory/allocator_arg_t.h
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___MEMORY_ALLOCATE_AT_LEAST_H
+#define _LIBCPP___MEMORY_ALLOCATE_AT_LEAST_H
+
+#include <__config>
+#include <__memory/allocator_traits.h>
+#include <cstddef>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER > 20
+template <class _Pointer>
+struct allocation_result {
+ _Pointer ptr;
+ size_t count;
+};
+
+template <class _Alloc>
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr
+allocation_result<typename allocator_traits<_Alloc>::pointer> allocate_at_least(_Alloc& __alloc, size_t __n) {
+ if constexpr (requires { __alloc.allocate_at_least(__n); }) {
+ return __alloc.allocate_at_least(__n);
+ } else {
+ return {__alloc.allocate(__n), __n};
+ }
+}
+
+template <class _Alloc>
+[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr
+auto __allocate_at_least(_Alloc& __alloc, size_t __n) {
+ return std::allocate_at_least(__alloc, __n);
+}
+#else
+template <class _Pointer>
+struct __allocation_result {
+ _Pointer ptr;
+ size_t count;
+};
+
+template <class _Alloc>
+_LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR
+__allocation_result<typename allocator_traits<_Alloc>::pointer> __allocate_at_least(_Alloc& __alloc, size_t __n) {
+ return {__alloc.allocate(__n), __n};
+}
+
+#endif // _LIBCPP_STD_VER > 20
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___MEMORY_ALLOCATE_AT_LEAST_H
#define _LIBCPP___MEMORY_ALLOCATOR_H
#include <__config>
+#include <__memory/allocate_at_least.h>
#include <__memory/allocator_traits.h>
#include <__utility/forward.h>
#include <cstddef>
}
}
+#if _LIBCPP_STD_VER > 20
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr
+ allocation_result<_Tp*> allocate_at_least(size_t __n) {
+ return {allocate(__n), __n};
+ }
+#endif
+
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
void deallocate(_Tp* __p, size_t __n) _NOEXCEPT {
if (__libcpp_is_constant_evaluated()) {
}
}
+#if _LIBCPP_STD_VER > 20
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr
+ allocation_result<const _Tp*> allocate_at_least(size_t __n) {
+ return {allocate(__n), __n};
+ }
+#endif
+
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
void deallocate(const _Tp* __p, size_t __n) {
if (__libcpp_is_constant_evaluated()) {
__split_buffer<_Tp, _Allocator>::__split_buffer(size_type __cap, size_type __start, __alloc_rr& __a)
: __end_cap_(nullptr, __a)
{
- __first_ = __cap != 0 ? __alloc_traits::allocate(__alloc(), __cap) : nullptr;
+ if (__cap == 0) {
+ __first_ = nullptr;
+ } else {
+ auto __allocation = std::__allocate_at_least(__alloc(), __cap);
+ __first_ = __allocation.ptr;
+ __cap = __allocation.count;
+ }
__begin_ = __end_ = __first_ + __start;
__end_cap() = __first_ + __cap;
}
}
else
{
- size_type __cap = __c.size();
- __first_ = __alloc_traits::allocate(__alloc(), __cap);
+ auto __allocation = std::__allocate_at_least(__alloc(), __c.size());
+ __first_ = __allocation.ptr;
__begin_ = __end_ = __first_;
- __end_cap() = __first_ + __cap;
+ __end_cap() = __first_ + __allocation.count;
typedef move_iterator<iterator> _Ip;
__construct_at_end(_Ip(__c.begin()), _Ip(__c.end()));
}
static allocator_type select_on_container_copy_construction(const allocator_type& a); // constexpr in C++20
};
+template<class Pointer>
+struct allocation_result {
+ Pointer ptr;
+ size_t count;
+}; // since C++23
+
+template<class Allocator>
+[[nodiscard]] constexpr allocation_result<typename allocator_traits<Allocator>::pointer>
+ allocate_at_least(Allocator& a, size_t n); // since C++23
+
template <>
class allocator<void> // removed in C++20
{
#include <__assert> // all public C++ headers provide the assertion handler
#include <__config>
#include <__memory/addressof.h>
+#include <__memory/allocate_at_least.h>
#include <__memory/allocation_guard.h>
#include <__memory/allocator.h>
#include <__memory/allocator_arg_t.h>
module __memory {
module addressof { private header "__memory/addressof.h" }
+ module allocate_at_least { private header "__memory/allocate_at_least.h" }
module allocation_guard { private header "__memory/allocation_guard.h" }
module allocator { private header "__memory/allocator.h" }
module allocator_arg_t { private header "__memory/allocator_arg_t.h" }
#include <__format/enable_insertable.h>
#include <__ios/fpos.h>
#include <__iterator/wrap_iter.h>
+#include <__memory/allocate_at_least.h>
#include <__utility/auto_cast.h>
#include <__utility/move.h>
#include <__utility/swap.h>
else
{
allocator_type __a = __str.__alloc();
- pointer __p = __alloc_traits::allocate(__a, __str.__get_long_cap());
+ auto __allocation = std::__allocate_at_least(__a, __str.__get_long_cap());
__clear_and_shrink();
__alloc() = _VSTD::move(__a);
- __set_long_pointer(__p);
- __set_long_cap(__str.__get_long_cap());
+ __set_long_pointer(__allocation.ptr);
+ __set_long_cap(__allocation.count);
__set_long_size(__str.size());
}
}
}
else
{
- size_type __cap = __recommend(__reserve);
- __p = __alloc_traits::allocate(__alloc(), __cap+1);
+ auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__reserve) + 1);
+ __p = __allocation.ptr;
__set_long_pointer(__p);
- __set_long_cap(__cap+1);
+ __set_long_cap(__allocation.count);
__set_long_size(__sz);
}
traits_type::copy(_VSTD::__to_address(__p), __s, __sz);
}
else
{
- size_type __cap = __recommend(__sz);
- __p = __alloc_traits::allocate(__alloc(), __cap+1);
+ auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1);
+ __p = __allocation.ptr;
__set_long_pointer(__p);
- __set_long_cap(__cap+1);
+ __set_long_cap(__allocation.count);
__set_long_size(__sz);
}
traits_type::copy(_VSTD::__to_address(__p), __s, __sz);
} else {
if (__sz > max_size())
__throw_length_error();
- size_t __cap = __recommend(__sz);
- __p = __alloc_traits::allocate(__alloc(), __cap + 1);
+ auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1);
+ __p = __allocation.ptr;
__set_long_pointer(__p);
- __set_long_cap(__cap + 1);
+ __set_long_cap(__allocation.count);
__set_long_size(__sz);
}
traits_type::copy(_VSTD::__to_address(__p), __s, __sz + 1);
}
else
{
- size_type __cap = __recommend(__n);
- __p = __alloc_traits::allocate(__alloc(), __cap+1);
+ auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__n) + 1);
+ __p = __allocation.ptr;
__set_long_pointer(__p);
- __set_long_cap(__cap+1);
+ __set_long_cap(__allocation.count);
__set_long_size(__n);
}
traits_type::assign(_VSTD::__to_address(__p), __n, __c);
}
else
{
- size_type __cap = __recommend(__sz);
- __p = __alloc_traits::allocate(__alloc(), __cap+1);
+ auto __allocation = std::__allocate_at_least(__alloc(), __recommend(__sz) + 1);
+ __p = __allocation.ptr;
__set_long_pointer(__p);
- __set_long_cap(__cap+1);
+ __set_long_cap(__allocation.count);
__set_long_size(__sz);
}
size_type __cap = __old_cap < __ms / 2 - __alignment ?
__recommend(_VSTD::max(__old_cap + __delta_cap, 2 * __old_cap)) :
__ms - 1;
- pointer __p = __alloc_traits::allocate(__alloc(), __cap+1);
+ auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1);
+ pointer __p = __allocation.ptr;
__invalidate_all_iterators();
if (__n_copy != 0)
traits_type::copy(_VSTD::__to_address(__p),
if (__old_cap+1 != __min_cap)
__alloc_traits::deallocate(__alloc(), __old_p, __old_cap+1);
__set_long_pointer(__p);
- __set_long_cap(__cap+1);
+ __set_long_cap(__allocation.count);
__old_sz = __n_copy + __n_add + __sec_cp_sz;
__set_long_size(__old_sz);
traits_type::assign(__p[__old_sz], value_type());
size_type __cap = __old_cap < __ms / 2 - __alignment ?
__recommend(_VSTD::max(__old_cap + __delta_cap, 2 * __old_cap)) :
__ms - 1;
- pointer __p = __alloc_traits::allocate(__alloc(), __cap+1);
+ auto __allocation = std::__allocate_at_least(__alloc(), __cap + 1);
+ pointer __p = __allocation.ptr;
__invalidate_all_iterators();
if (__n_copy != 0)
traits_type::copy(_VSTD::__to_address(__p),
if (__old_cap+1 != __min_cap)
__alloc_traits::deallocate(__alloc(), __old_p, __old_cap+1);
__set_long_pointer(__p);
- __set_long_cap(__cap+1);
+ __set_long_cap(__allocation.count);
}
// assign
}
else
{
- if (__target_capacity > __cap)
- __new_data = __alloc_traits::allocate(__alloc(), __target_capacity+1);
+ if (__target_capacity > __cap) {
+ auto __allocation = std::__allocate_at_least(__alloc(), __target_capacity + 1);
+ __new_data = __allocation.ptr;
+ __target_capacity = __allocation.count - 1;
+ }
else
{
#ifndef _LIBCPP_NO_EXCEPTIONS
try
{
#endif // _LIBCPP_NO_EXCEPTIONS
- __new_data = __alloc_traits::allocate(__alloc(), __target_capacity+1);
+ auto __allocation = std::__allocate_at_least(__alloc(), __target_capacity + 1);
+ __new_data = __allocation.ptr;
+ __target_capacity = __allocation.count - 1;
#ifndef _LIBCPP_NO_EXCEPTIONS
}
catch (...)
#include <__functional/hash.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/wrap_iter.h>
+#include <__memory/allocate_at_least.h>
#include <__split_buffer>
#include <__utility/forward.h>
#include <__utility/move.h>
_LIBCPP_INLINE_VISIBILITY void __invalidate_all_iterators();
_LIBCPP_INLINE_VISIBILITY void __invalidate_iterators_past(pointer __new_last);
- void __vallocate(size_type __n);
+
+
+ // Allocate space for __n objects
+ // throws length_error if __n > max_size()
+ // throws (probably bad_alloc) if memory run out
+ // Precondition: __begin_ == __end_ == __end_cap() == 0
+ // Precondition: __n > 0
+ // Postcondition: capacity() >= __n
+ // Postcondition: size() == 0
+ _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) {
+ if (__n > max_size())
+ __throw_length_error();
+ auto __allocation = std::__allocate_at_least(__alloc(), __n);
+ __begin_ = __allocation.ptr;
+ __end_ = __allocation.ptr;
+ __end_cap() = __begin_ + __allocation.count;
+ __annotate_new(0);
+ }
+
void __vdeallocate() _NOEXCEPT;
_LIBCPP_INLINE_VISIBILITY size_type __recommend(size_type __new_size) const;
void __construct_at_end(size_type __n);
return __r;
}
-// Allocate space for __n objects
-// throws length_error if __n > max_size()
-// throws (probably bad_alloc) if memory run out
-// Precondition: __begin_ == __end_ == __end_cap() == 0
-// Precondition: __n > 0
-// Postcondition: capacity() == __n
-// Postcondition: size() == 0
-template <class _Tp, class _Allocator>
-void
-vector<_Tp, _Allocator>::__vallocate(size_type __n)
-{
- if (__n > max_size())
- this->__throw_length_error();
- this->__begin_ = this->__end_ = __alloc_traits::allocate(this->__alloc(), __n);
- this->__end_cap() = this->__begin_ + __n;
- __annotate_new(0);
-}
-
template <class _Tp, class _Allocator>
void
vector<_Tp, _Allocator>::__vdeallocate() _NOEXCEPT
_VSTD::__throw_out_of_range("vector");
}
+ // Allocate space for __n objects
+ // throws length_error if __n > max_size()
+ // throws (probably bad_alloc) if memory run out
+ // Precondition: __begin_ == __end_ == __cap() == 0
+ // Precondition: __n > 0
+ // Postcondition: capacity() >= __n
+ // Postcondition: size() == 0
_LIBCPP_INLINE_VISIBILITY void __invalidate_all_iterators();
- void __vallocate(size_type __n);
+ _LIBCPP_HIDE_FROM_ABI void __vallocate(size_type __n) {
+ if (__n > max_size())
+ __throw_length_error();
+ auto __allocation = std::__allocate_at_least(__alloc(), __external_cap_to_internal(__n));
+ __begin_ = __allocation.ptr;
+ __size_ = 0;
+ __cap() = __allocation.count;
+ }
+
void __vdeallocate() _NOEXCEPT;
_LIBCPP_INLINE_VISIBILITY
static size_type __align_it(size_type __new_size) _NOEXCEPT
{
}
-// Allocate space for __n objects
-// throws length_error if __n > max_size()
-// throws (probably bad_alloc) if memory run out
-// Precondition: __begin_ == __end_ == __cap() == 0
-// Precondition: __n > 0
-// Postcondition: capacity() == __n
-// Postcondition: size() == 0
-template <class _Allocator>
-void
-vector<bool, _Allocator>::__vallocate(size_type __n)
-{
- if (__n > max_size())
- this->__throw_length_error();
- __n = __external_cap_to_internal(__n);
- this->__begin_ = __storage_traits::allocate(this->__alloc(), __n);
- this->__size_ = 0;
- this->__cap() = __n;
-}
-
template <class _Allocator>
void
vector<bool, _Allocator>::__vdeallocate() _NOEXCEPT
#if _LIBCPP_STD_VER > 20
# define __cpp_lib_adaptor_iterator_pair_constructor 202106L
-// # define __cpp_lib_allocate_at_least 202106L
+# define __cpp_lib_allocate_at_least 202106L
// # define __cpp_lib_associative_heterogeneous_erasure 202110L
// # define __cpp_lib_bind_back 202202L
# define __cpp_lib_byteswap 202110L
#include <__locale> // expected-error@*:* {{use of private header from outside its module: '__locale'}}
#include <__mbstate_t.h> // expected-error@*:* {{use of private header from outside its module: '__mbstate_t.h'}}
#include <__memory/addressof.h> // expected-error@*:* {{use of private header from outside its module: '__memory/addressof.h'}}
+#include <__memory/allocate_at_least.h> // expected-error@*:* {{use of private header from outside its module: '__memory/allocate_at_least.h'}}
#include <__memory/allocation_guard.h> // expected-error@*:* {{use of private header from outside its module: '__memory/allocation_guard.h'}}
#include <__memory/allocator.h> // expected-error@*:* {{use of private header from outside its module: '__memory/allocator.h'}}
#include <__memory/allocator_arg_t.h> // expected-error@*:* {{use of private header from outside its module: '__memory/allocator_arg_t.h'}}
# error "__cpp_lib_addressof_constexpr should have the value 201603L in c++2b"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_allocate_at_least
-# error "__cpp_lib_allocate_at_least should be defined in c++2b"
-# endif
-# if __cpp_lib_allocate_at_least != 202106L
-# error "__cpp_lib_allocate_at_least should have the value 202106L in c++2b"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_allocate_at_least
-# error "__cpp_lib_allocate_at_least should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_allocate_at_least
+# error "__cpp_lib_allocate_at_least should be defined in c++2b"
+# endif
+# if __cpp_lib_allocate_at_least != 202106L
+# error "__cpp_lib_allocate_at_least should have the value 202106L in c++2b"
# endif
# ifndef __cpp_lib_allocator_traits_is_always_equal
# error "__cpp_lib_addressof_constexpr should have the value 201603L in c++2b"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_allocate_at_least
-# error "__cpp_lib_allocate_at_least should be defined in c++2b"
-# endif
-# if __cpp_lib_allocate_at_least != 202106L
-# error "__cpp_lib_allocate_at_least should have the value 202106L in c++2b"
-# endif
-# else // _LIBCPP_VERSION
-# ifdef __cpp_lib_allocate_at_least
-# error "__cpp_lib_allocate_at_least should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_allocate_at_least
+# error "__cpp_lib_allocate_at_least should be defined in c++2b"
+# endif
+# if __cpp_lib_allocate_at_least != 202106L
+# error "__cpp_lib_allocate_at_least should have the value 202106L in c++2b"
# endif
# ifndef __cpp_lib_allocator_traits_is_always_equal
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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, c++20
+
+// <memory>
+
+// template<class Allocator>
+// [[nodiscard]] constexpr allocation_result<typename allocator_traits<Allocator>::pointer>
+// allocate_at_least(Allocator& a, size_t n);
+
+#include <cassert>
+#include <memory>
+
+// check that std::allocation_result exists and isn't restricted to pointers
+using AllocResult = std::allocation_result<int>;
+
+template <class T>
+struct no_allocate_at_least {
+ using value_type = T;
+ T t;
+
+ constexpr T* allocate(size_t) { return &t; }
+ constexpr void deallocate(T*, size_t) {}
+};
+
+template <class T>
+struct has_allocate_at_least {
+ using value_type = T;
+ T t1;
+ T t2;
+
+ constexpr T* allocate(size_t) { return &t1; }
+ constexpr void deallocate(T*, size_t) {}
+ constexpr std::allocation_result<T*> allocate_at_least(size_t) {
+ return {&t2, 2};
+ }
+};
+
+constexpr bool test() {
+ { // check that std::allocate_at_least forwards to allocator::allocate if no allocate_at_least exists
+ no_allocate_at_least<int> alloc;
+ std::same_as<std::allocation_result<int*>> decltype(auto) ret = std::allocate_at_least(alloc, 1);
+ assert(ret.count == 1);
+ assert(ret.ptr == &alloc.t);
+ }
+
+ { // check that std::allocate_at_least forwards to allocator::allocate_at_least if allocate_at_least exists
+ has_allocate_at_least<int> alloc;
+ std::same_as<std::allocation_result<int*>> decltype(auto) ret = std::allocate_at_least(alloc, 1);
+ assert(ret.count == 2);
+ assert(ret.ptr == &alloc.t2);
+ }
+
+ return true;
+}
+
+int main() {
+ test();
+ static_assert(test());
+}
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// 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, c++20
+
+// <memory>
+
+// allocation_result<T*> allocate_at_least(size_t n)
+
+#include <cassert>
+#include <memory>
+
+#include "count_new.h"
+
+#ifdef TEST_HAS_NO_ALIGNED_ALLOCATION
+static const bool UsingAlignedNew = false;
+#else
+static const bool UsingAlignedNew = true;
+#endif
+
+#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
+static const size_t MaxAligned = __STDCPP_DEFAULT_NEW_ALIGNMENT__;
+#else
+static const size_t MaxAligned = std::alignment_of<std::max_align_t>::value;
+#endif
+
+static const size_t OverAligned = MaxAligned * 2;
+
+template <size_t Align>
+struct alignas(Align) AlignedType {
+ char data;
+ static int constructed;
+ AlignedType() { ++constructed; }
+ AlignedType(AlignedType const&) { ++constructed; }
+ ~AlignedType() { --constructed; }
+};
+template <size_t Align>
+int AlignedType<Align>::constructed = 0;
+
+
+template <size_t Align>
+void test_aligned() {
+ typedef AlignedType<Align> T;
+ T::constructed = 0;
+ globalMemCounter.reset();
+ std::allocator<T> a;
+ const bool IsOverAlignedType = Align > MaxAligned;
+ const bool ExpectAligned = IsOverAlignedType && UsingAlignedNew;
+ {
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ assert(T::constructed == 0);
+ globalMemCounter.last_new_size = 0;
+ globalMemCounter.last_new_align = 0;
+ std::same_as<std::allocation_result<T*>> decltype(auto) ap = a.allocate_at_least(3);
+ assert(ap.count >= 3);
+ DoNotOptimize(ap);
+ assert(globalMemCounter.checkOutstandingNewEq(1));
+ assert(globalMemCounter.checkNewCalledEq(1));
+ assert(globalMemCounter.checkAlignedNewCalledEq(ExpectAligned));
+ assert(globalMemCounter.checkLastNewSizeEq(3 * sizeof(T)));
+ assert(globalMemCounter.checkLastNewAlignEq(ExpectAligned ? Align : 0));
+ assert(T::constructed == 0);
+ globalMemCounter.last_delete_align = 0;
+ a.deallocate(ap.ptr, 3);
+ assert(globalMemCounter.checkOutstandingNewEq(0));
+ assert(globalMemCounter.checkDeleteCalledEq(1));
+ assert(globalMemCounter.checkAlignedDeleteCalledEq(ExpectAligned));
+ assert(globalMemCounter.checkLastDeleteAlignEq(ExpectAligned ? Align : 0));
+ assert(T::constructed == 0);
+ }
+}
+
+template <size_t Align>
+constexpr bool test_aligned_constexpr() {
+ typedef AlignedType<Align> T;
+ std::allocator<T> a;
+ std::same_as<std::allocation_result<T*>> decltype(auto) ap = a.allocate_at_least(3);
+ assert(ap.count >= 3);
+ a.deallocate(ap.ptr, 3);
+
+ return true;
+}
+
+int main(int, char**) {
+ test_aligned<1>();
+ test_aligned<2>();
+ test_aligned<4>();
+ test_aligned<8>();
+ test_aligned<16>();
+ test_aligned<MaxAligned>();
+ test_aligned<OverAligned>();
+ test_aligned<OverAligned * 2>();
+
+ static_assert(test_aligned_constexpr<1>());
+ static_assert(test_aligned_constexpr<2>());
+ static_assert(test_aligned_constexpr<4>());
+ static_assert(test_aligned_constexpr<8>());
+ static_assert(test_aligned_constexpr<16>());
+ static_assert(test_aligned_constexpr<MaxAligned>());
+ static_assert(test_aligned_constexpr<OverAligned>());
+ static_assert(test_aligned_constexpr<OverAligned * 2>());
+ return 0;
+}
"name": "__cpp_lib_allocate_at_least",
"values": { "c++2b": 202106 },
"headers": ["memory"],
- "unimplemented": True,
}, {
"name": "__cpp_lib_allocator_traits_is_always_equal",
"values": { "c++17": 201411 },