1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // <memory>
11 
12 // allocator:
13 // template <class... Args> void construct(pointer p, Args&&... args);
14 
15 #include <memory>
16 #include <new>
17 #include <cstdlib>
18 #include <cassert>
19 
20 int new_called = 0;
21 
22 void* operator new(std::size_t s) throw(std::bad_alloc)
23 {
24     ++new_called;
25     assert(s == 3 * sizeof(int));
26     return std::malloc(s);
27 }
28 
29 void  operator delete(void* p) throw()
30 {
31     --new_called;
32     std::free(p);
33 }
34 
35 int A_constructed = 0;
36 
37 struct A
38 {
39     int data;
40     A() {++A_constructed;}
41 
42     A(const A&) {++A_constructed;}
43 
44     explicit A(int) {++A_constructed;}
45     A(int, int*) {++A_constructed;}
46 
47     ~A() {--A_constructed;}
48 };
49 
50 int move_only_constructed = 0;
51 
52 class move_only
53 {
54     int data;
55 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
56     move_only(const move_only&);
57     move_only& operator=(const move_only&);
58 #else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
59     move_only(move_only&);
60     move_only& operator=(move_only&);
61 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
62 
63 public:
64 
65 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
66     move_only(move_only&&) {++move_only_constructed;}
67     move_only& operator=(move_only&&) {return *this;}
68 #else  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
69     operator std::__rv<move_only> () {return std::__rv<move_only>(*this);}
70     move_only(std::__rv<move_only>) {++move_only_constructed;}
71 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
72 
73     move_only() {++move_only_constructed;}
74     ~move_only() {--move_only_constructed;}
75 };
76 
77 int main()
78 {
79     {
80     std::allocator<A> a;
81     assert(new_called == 0);
82     assert(A_constructed == 0);
83 
84     A* ap = a.allocate(3);
85     assert(new_called == 1);
86     assert(A_constructed == 0);
87 
88     a.construct(ap);
89     assert(new_called == 1);
90     assert(A_constructed == 1);
91 
92     a.destroy(ap);
93     assert(new_called == 1);
94     assert(A_constructed == 0);
95 
96     a.construct(ap, A());
97     assert(new_called == 1);
98     assert(A_constructed == 1);
99 
100     a.destroy(ap);
101     assert(new_called == 1);
102     assert(A_constructed == 0);
103 
104     a.construct(ap, 5);
105     assert(new_called == 1);
106     assert(A_constructed == 1);
107 
108     a.destroy(ap);
109     assert(new_called == 1);
110     assert(A_constructed == 0);
111 
112     a.construct(ap, 5, (int*)0);
113     assert(new_called == 1);
114     assert(A_constructed == 1);
115 
116     a.destroy(ap);
117     assert(new_called == 1);
118     assert(A_constructed == 0);
119 
120     a.deallocate(ap, 3);
121     assert(new_called == 0);
122     assert(A_constructed == 0);
123     }
124     {
125     std::allocator<move_only> a;
126     assert(new_called == 0);
127     assert(move_only_constructed == 0);
128 
129     move_only* ap = a.allocate(3);
130     assert(new_called == 1);
131     assert(move_only_constructed == 0);
132 
133     a.construct(ap);
134     assert(new_called == 1);
135     assert(move_only_constructed == 1);
136 
137     a.destroy(ap);
138     assert(new_called == 1);
139     assert(move_only_constructed == 0);
140 
141     a.construct(ap, move_only());
142     assert(new_called == 1);
143     assert(move_only_constructed == 1);
144 
145     a.destroy(ap);
146     assert(new_called == 1);
147     assert(move_only_constructed == 0);
148 
149     a.deallocate(ap, 3);
150     assert(new_called == 0);
151     assert(move_only_constructed == 0);
152     }
153 }
154