construct.pass.cpp revision 6b41c6047ba9016a4a183fd77522db941bc32392
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
20int new_called = 0;
21
22void* 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
29void  operator delete(void* p) throw()
30{
31    --new_called;
32    std::free(p);
33}
34
35int A_constructed = 0;
36
37struct 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
50int move_only_constructed = 0;
51
52class 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
63public:
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
77int 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