// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // ManualConstructor statically-allocates space in which to store some // object, but does not initialize it. You can then call the constructor // and destructor for the object yourself as you see fit. This is useful // for memory management optimizations, where you want to initialize and // destroy an object multiple times but only allocate it once. // // (When I say ManualConstructor statically allocates space, I mean that // the ManualConstructor object itself is forced to be the right size.) // // For example usage, check out base/containers/small_map.h. #ifndef BASE_MEMORY_MANUAL_CONSTRUCTOR_H_ #define BASE_MEMORY_MANUAL_CONSTRUCTOR_H_ #include <stddef.h> #include "base/memory/aligned_memory.h" namespace base { template <typename Type> class ManualConstructor { public: // No constructor or destructor because one of the most useful uses of // this class is as part of a union, and members of a union cannot have // constructors or destructors. And, anyway, the whole point of this // class is to bypass these. // Support users creating arrays of ManualConstructor<>s. This ensures that // the array itself has the correct alignment. static void* operator new[](size_t size) { #if defined(COMPILER_MSVC) return AlignedAlloc(size, __alignof(Type)); #else return AlignedAlloc(size, __alignof__(Type)); #endif } static void operator delete[](void* mem) { AlignedFree(mem); } inline Type* get() { return space_.template data_as<Type>(); } inline const Type* get() const { return space_.template data_as<Type>(); } inline Type* operator->() { return get(); } inline const Type* operator->() const { return get(); } inline Type& operator*() { return *get(); } inline const Type& operator*() const { return *get(); } // You can pass up to eight constructor arguments as arguments of Init(). inline void Init() { new(space_.void_data()) Type; } template <typename T1> inline void Init(const T1& p1) { new(space_.void_data()) Type(p1); } template <typename T1, typename T2> inline void Init(const T1& p1, const T2& p2) { new(space_.void_data()) Type(p1, p2); } template <typename T1, typename T2, typename T3> inline void Init(const T1& p1, const T2& p2, const T3& p3) { new(space_.void_data()) Type(p1, p2, p3); } template <typename T1, typename T2, typename T3, typename T4> inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4) { new(space_.void_data()) Type(p1, p2, p3, p4); } template <typename T1, typename T2, typename T3, typename T4, typename T5> inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, const T5& p5) { new(space_.void_data()) Type(p1, p2, p3, p4, p5); } template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, const T5& p5, const T6& p6) { new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6); } template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7> inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, const T5& p5, const T6& p6, const T7& p7) { new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6, p7); } template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4, const T5& p5, const T6& p6, const T7& p7, const T8& p8) { new(space_.void_data()) Type(p1, p2, p3, p4, p5, p6, p7, p8); } inline void Destroy() { get()->~Type(); } private: #if defined(COMPILER_MSVC) AlignedMemory<sizeof(Type), __alignof(Type)> space_; #else AlignedMemory<sizeof(Type), __alignof__(Type)> space_; #endif }; } // namespace base #endif // BASE_MEMORY_MANUAL_CONSTRUCTOR_H_