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. 4 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. 10 // 11 // (When I say ManualConstructor statically allocates space, I mean that 12 // the ManualConstructor object itself is forced to be the right size.) 13 // 14 // For example usage, check out base/containers/small_map.h. 15 16 #ifndef BASE_MEMORY_MANUAL_CONSTRUCTOR_H_ 17 #define BASE_MEMORY_MANUAL_CONSTRUCTOR_H_ 18 19 #include <stddef.h> 20 21 #include "base/memory/aligned_memory.h" 22 23 namespace base { 24 25 template <typename Type> 26 class ManualConstructor { 27 public: 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. 32 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)); 38 #else 39 return AlignedAlloc(size, __alignof__(Type)); 40 #endif 41 } 42 static void operator delete[](void* mem) { 43 AlignedFree(mem); 44 } 45 46 inline Type* get() { 47 return space_.template data_as<Type>(); 48 } 49 inline const Type* get() const { 50 return space_.template data_as<Type>(); 51 } 52 53 inline Type* operator->() { return get(); } 54 inline const Type* operator->() const { return get(); } 55 56 inline Type& operator*() { return *get(); } 57 inline const Type& operator*() const { return *get(); } 58 59 // You can pass up to eight constructor arguments as arguments of Init(). 60 inline void Init() { 61 new(space_.void_data()) Type; 62 } 63 64 template <typename T1> 65 inline void Init(const T1& p1) { 66 new(space_.void_data()) Type(p1); 67 } 68 69 template <typename T1, typename T2> 70 inline void Init(const T1& p1, const T2& p2) { 71 new(space_.void_data()) Type(p1, p2); 72 } 73 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); 77 } 78 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); 82 } 83 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, 86 const T5& p5) { 87 new(space_.void_data()) Type(p1, p2, p3, p4, p5); 88 } 89 90 template <typename T1, typename T2, typename T3, typename T4, typename T5, 91 typename T6> 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); 95 } 96 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); 102 } 103 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); 109 } 110 111 inline void Destroy() { 112 get()->~Type(); 113 } 114 115 private: 116 #if defined(COMPILER_MSVC) 117 AlignedMemory<sizeof(Type), __alignof(Type)> space_; 118 #else 119 AlignedMemory<sizeof(Type), __alignof__(Type)> space_; 120 #endif 121 }; 122 123 } // namespace base 124 125 #endif // BASE_MEMORY_MANUAL_CONSTRUCTOR_H_ 126