1 //===----------------------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
13 // template<class T, class A, class... Args>
14 // shared_ptr<T> allocate_shared(const A& a, Args&&... args);
16 // This test checks that allocator_traits::construct and allocator_traits::destroy
17 // are used in allocate_shared as requested for the resolution of LWG2070. Note
18 // that LWG2070 was resolved by P0674R1 (which is a C++20 paper), but we implement
19 // LWG issue resolutions as DRs per our policy.
28 #include "test_macros.h"
30 static bool construct_called
= false;
31 static bool destroy_called
= false;
32 static unsigned allocator_id
= 0;
42 MyAllocator() = default;
43 MyAllocator(int i
) : id(i
) {}
46 MyAllocator(MyAllocator
<U
> const& other
) : id(other
.id
) {}
48 pointer
allocate(std::ptrdiff_t n
) {
49 return pointer(static_cast<T
*>(::operator new(n
* sizeof(T
))));
52 void deallocate(pointer p
, std::ptrdiff_t) { return ::operator delete(p
); }
54 template <typename
...Args
>
55 void construct(T
* p
, Args
&& ...args
) {
56 construct_called
= true;
57 destroy_called
= false;
59 ::new (p
) T(std::forward
<Args
>(args
)...);
63 construct_called
= false;
64 destroy_called
= true;
74 static std::shared_ptr
<Private
> allocate();
78 struct FactoryAllocator
;
84 friend FactoryAllocator
<Private
>;
85 Private(int i
) : id(i
) {}
90 struct FactoryAllocator
: std::allocator
<T
> {
91 FactoryAllocator() = default;
94 FactoryAllocator(FactoryAllocator
<T1
>) {}
98 typedef FactoryAllocator
<T1
> other
;
101 void construct(void* p
, int id
) { ::new (p
) Private(id
); }
102 void destroy(Private
* p
) { p
->~Private(); }
105 std::shared_ptr
<Private
> Factory::allocate() {
106 FactoryAllocator
<Private
> factory_alloc
;
107 return std::allocate_shared
<Private
>(factory_alloc
, 42);
117 Foo(int v
) : val(v
) {}
119 Foo(Foo a
, Foo b
) : val(a
.val
+ b
.val
) {}
122 void test_aligned(void* p
, std::size_t align
) {
123 assert(reinterpret_cast<std::uintptr_t>(p
) % align
== 0);
126 int main(int, char**) {
128 std::shared_ptr
<int> p
= std::allocate_shared
<int>(MyAllocator
<int>());
129 assert(construct_called
);
131 assert(destroy_called
);
133 std::shared_ptr
<Foo
> p
=
134 std::allocate_shared
<Foo
>(MyAllocator
<Foo
>(), Foo(42), Foo(100));
135 assert(construct_called
);
136 assert(p
->val
== 142);
138 assert(destroy_called
);
139 { // Make sure allocator is copied.
140 std::shared_ptr
<int> p
= std::allocate_shared
<int>(MyAllocator
<int>(3));
141 assert(allocator_id
== 3);
145 assert(allocator_id
== 3);
148 std::shared_ptr
<int> p
= std::allocate_shared
<int>(MyAllocator
<int>(), 42);
149 assert(construct_called
);
152 assert(destroy_called
);
154 { // Make sure allocator is properly re-bound.
155 std::shared_ptr
<int> p
=
156 std::allocate_shared
<int>(MyAllocator
<mchar
>(), 42);
157 assert(construct_called
);
160 assert(destroy_called
);
163 // Make sure that we call the correct allocator::construct. Private has a private constructor
164 // so the construct method must be called on its friend Factory's allocator
165 // (Factory::Allocator).
166 std::shared_ptr
<Private
> p
= Factory().allocate();
170 #if TEST_STD_VER >= 11
176 std::shared_ptr
<Bar
> p
;
177 test_aligned(p
.get(), alignof(Bar
));