1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 // ManualConstructor statically-allocates space in which to store some
6 // object, but does not initialize it. You can then call the constructor
7 // and destructor for the object yourself as you see fit. This is useful
8 // for memory management optimizations, where you want to initialize and
9 // destroy an object multiple times but only allocate it once.
11 // (When I say ManualConstructor statically allocates space, I mean that
12 // the ManualConstructor object itself is forced to be the right size.)
14 // For example usage, check out base/containers/small_map.h.
16 #ifndef BASE_MEMORY_MANUAL_CONSTRUCTOR_H_
17 #define BASE_MEMORY_MANUAL_CONSTRUCTOR_H_
21 #include "base/memory/aligned_memory.h"
25 template <typename Type
>
26 class ManualConstructor
{
28 // No constructor or destructor because one of the most useful uses of
29 // this class is as part of a union, and members of a union cannot have
30 // constructors or destructors. And, anyway, the whole point of this
31 // class is to bypass these.
33 // Support users creating arrays of ManualConstructor<>s. This ensures that
34 // the array itself has the correct alignment.
35 static void* operator new[](size_t size
) {
36 #if defined(COMPILER_MSVC)
37 return AlignedAlloc(size
, __alignof(Type
));
39 return AlignedAlloc(size
, __alignof__(Type
));
42 static void operator delete[](void* mem
) {
47 return space_
.template data_as
<Type
>();
49 inline const Type
* get() const {
50 return space_
.template data_as
<Type
>();
53 inline Type
* operator->() { return get(); }
54 inline const Type
* operator->() const { return get(); }
56 inline Type
& operator*() { return *get(); }
57 inline const Type
& operator*() const { return *get(); }
59 // You can pass up to eight constructor arguments as arguments of Init().
61 new(space_
.void_data()) Type
;
64 template <typename T1
>
65 inline void Init(const T1
& p1
) {
66 new(space_
.void_data()) Type(p1
);
69 template <typename T1
, typename T2
>
70 inline void Init(const T1
& p1
, const T2
& p2
) {
71 new(space_
.void_data()) Type(p1
, p2
);
74 template <typename T1
, typename T2
, typename T3
>
75 inline void Init(const T1
& p1
, const T2
& p2
, const T3
& p3
) {
76 new(space_
.void_data()) Type(p1
, p2
, p3
);
79 template <typename T1
, typename T2
, typename T3
, typename T4
>
80 inline void Init(const T1
& p1
, const T2
& p2
, const T3
& p3
, const T4
& p4
) {
81 new(space_
.void_data()) Type(p1
, p2
, p3
, p4
);
84 template <typename T1
, typename T2
, typename T3
, typename T4
, typename T5
>
85 inline void Init(const T1
& p1
, const T2
& p2
, const T3
& p3
, const T4
& p4
,
87 new(space_
.void_data()) Type(p1
, p2
, p3
, p4
, p5
);
90 template <typename T1
, typename T2
, typename T3
, typename T4
, typename T5
,
92 inline void Init(const T1
& p1
, const T2
& p2
, const T3
& p3
, const T4
& p4
,
93 const T5
& p5
, const T6
& p6
) {
94 new(space_
.void_data()) Type(p1
, p2
, p3
, p4
, p5
, p6
);
97 template <typename T1
, typename T2
, typename T3
, typename T4
, typename T5
,
98 typename T6
, typename T7
>
99 inline void Init(const T1
& p1
, const T2
& p2
, const T3
& p3
, const T4
& p4
,
100 const T5
& p5
, const T6
& p6
, const T7
& p7
) {
101 new(space_
.void_data()) Type(p1
, p2
, p3
, p4
, p5
, p6
, p7
);
104 template <typename T1
, typename T2
, typename T3
, typename T4
, typename T5
,
105 typename T6
, typename T7
, typename T8
>
106 inline void Init(const T1
& p1
, const T2
& p2
, const T3
& p3
, const T4
& p4
,
107 const T5
& p5
, const T6
& p6
, const T7
& p7
, const T8
& p8
) {
108 new(space_
.void_data()) Type(p1
, p2
, p3
, p4
, p5
, p6
, p7
, p8
);
111 inline void Destroy() {
116 #if defined(COMPILER_MSVC)
117 AlignedMemory
<sizeof(Type
), __alignof(Type
)> space_
;
119 AlignedMemory
<sizeof(Type
), __alignof__(Type
)> space_
;
125 #endif // BASE_MEMORY_MANUAL_CONSTRUCTOR_H_