blob: 174d35ee2bd0bb05a3f9e622dab2f14821347bf9 [file] [log] [blame]
Keir Mierle8ebb0732012-04-30 23:09:08 -07001// Ceres Solver - A fast non-linear least squares minimizer
2// Copyright 2010, 2011, 2012 Google Inc. All rights reserved.
3// http://code.google.com/p/ceres-solver/
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are met:
7//
8// * Redistributions of source code must retain the above copyright notice,
9// this list of conditions and the following disclaimer.
10// * Redistributions in binary form must reproduce the above copyright notice,
11// this list of conditions and the following disclaimer in the documentation
12// and/or other materials provided with the distribution.
13// * Neither the name of Google Inc. nor the names of its contributors may be
14// used to endorse or promote products derived from this software without
15// specific prior written permission.
16//
17// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27// POSSIBILITY OF SUCH DAMAGE.
28//
29// Author: kenton@google.com (Kenton Varda)
30//
31// ManualConstructor statically-allocates space in which to store some
32// object, but does not initialize it. You can then call the constructor
33// and destructor for the object yourself as you see fit. This is useful
34// for memory management optimizations, where you want to initialize and
35// destroy an object multiple times but only allocate it once.
36//
37// (When I say ManualConstructor statically allocates space, I mean that
38// the ManualConstructor object itself is forced to be the right size.)
39
40#ifndef CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_
41#define CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_
42
43#include <new>
44
45namespace ceres {
46namespace internal {
47
Sameer Agarwaleb893402012-06-17 08:55:01 -070048// ------- Define CERES_ALIGNED_CHAR_ARRAY --------------------------------
Keir Mierle8ebb0732012-04-30 23:09:08 -070049
Sameer Agarwaleb893402012-06-17 08:55:01 -070050#ifndef CERES_ALIGNED_CHAR_ARRAY
Keir Mierle8ebb0732012-04-30 23:09:08 -070051
52// Because MSVC and older GCCs require that the argument to their alignment
53// construct to be a literal constant integer, we use a template instantiated
54// at all the possible powers of two.
55template<int alignment, int size> struct AlignType { };
56template<int size> struct AlignType<0, size> { typedef char result[size]; };
Keir Mierle8ebb0732012-04-30 23:09:08 -070057
Sameer Agarwaleb893402012-06-17 08:55:01 -070058#if !defined(CERES_ALIGN_ATTRIBUTE)
59#define CERES_ALIGNED_CHAR_ARRAY you_must_define_CERES_ALIGNED_CHAR_ARRAY_for_your_compiler
60#else // !defined(CERES_ALIGN_ATTRIBUTE)
Keir Mierle8ebb0732012-04-30 23:09:08 -070061
Sameer Agarwaleb893402012-06-17 08:55:01 -070062#define CERES_ALIGN_TYPE_TEMPLATE(X) \
Keir Mierle8ebb0732012-04-30 23:09:08 -070063 template<int size> struct AlignType<X, size> { \
Sameer Agarwaleb893402012-06-17 08:55:01 -070064 typedef CERES_ALIGN_ATTRIBUTE(X) char result[size]; \
Keir Mierle8ebb0732012-04-30 23:09:08 -070065 }
66
Sameer Agarwaleb893402012-06-17 08:55:01 -070067CERES_ALIGN_TYPE_TEMPLATE(1);
68CERES_ALIGN_TYPE_TEMPLATE(2);
69CERES_ALIGN_TYPE_TEMPLATE(4);
70CERES_ALIGN_TYPE_TEMPLATE(8);
71CERES_ALIGN_TYPE_TEMPLATE(16);
72CERES_ALIGN_TYPE_TEMPLATE(32);
73CERES_ALIGN_TYPE_TEMPLATE(64);
74CERES_ALIGN_TYPE_TEMPLATE(128);
75CERES_ALIGN_TYPE_TEMPLATE(256);
76CERES_ALIGN_TYPE_TEMPLATE(512);
77CERES_ALIGN_TYPE_TEMPLATE(1024);
78CERES_ALIGN_TYPE_TEMPLATE(2048);
79CERES_ALIGN_TYPE_TEMPLATE(4096);
80CERES_ALIGN_TYPE_TEMPLATE(8192);
Keir Mierle8ebb0732012-04-30 23:09:08 -070081// Any larger and MSVC++ will complain.
82
Sameer Agarwaleb893402012-06-17 08:55:01 -070083#undef CERES_ALIGN_TYPE_TEMPLATE
Keir Mierle8ebb0732012-04-30 23:09:08 -070084
Sameer Agarwaleb893402012-06-17 08:55:01 -070085#define CERES_ALIGNED_CHAR_ARRAY(T, Size) \
86 typename AlignType<CERES_ALIGN_OF(T), sizeof(T) * Size>::result
Keir Mierle8ebb0732012-04-30 23:09:08 -070087
Sameer Agarwaleb893402012-06-17 08:55:01 -070088#endif // !defined(CERES_ALIGN_ATTRIBUTE)
Keir Mierle8ebb0732012-04-30 23:09:08 -070089
Sameer Agarwaleb893402012-06-17 08:55:01 -070090#endif // CERES_ALIGNED_CHAR_ARRAY
Keir Mierle8ebb0732012-04-30 23:09:08 -070091
92template <typename Type>
93class ManualConstructor {
94 public:
95 // No constructor or destructor because one of the most useful uses of
96 // this class is as part of a union, and members of a union cannot have
97 // constructors or destructors. And, anyway, the whole point of this
98 // class is to bypass these.
99
100 inline Type* get() {
101 return reinterpret_cast<Type*>(space_);
102 }
103 inline const Type* get() const {
104 return reinterpret_cast<const Type*>(space_);
105 }
106
107 inline Type* operator->() { return get(); }
108 inline const Type* operator->() const { return get(); }
109
110 inline Type& operator*() { return *get(); }
111 inline const Type& operator*() const { return *get(); }
112
113 // You can pass up to four constructor arguments as arguments of Init().
114 inline void Init() {
115 new(space_) Type;
116 }
117
118 template <typename T1>
119 inline void Init(const T1& p1) {
120 new(space_) Type(p1);
121 }
122
123 template <typename T1, typename T2>
124 inline void Init(const T1& p1, const T2& p2) {
125 new(space_) Type(p1, p2);
126 }
127
128 template <typename T1, typename T2, typename T3>
129 inline void Init(const T1& p1, const T2& p2, const T3& p3) {
130 new(space_) Type(p1, p2, p3);
131 }
132
133 template <typename T1, typename T2, typename T3, typename T4>
134 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4) {
135 new(space_) Type(p1, p2, p3, p4);
136 }
137
138 template <typename T1, typename T2, typename T3, typename T4, typename T5>
139 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
140 const T5& p5) {
141 new(space_) Type(p1, p2, p3, p4, p5);
142 }
143
144 template <typename T1, typename T2, typename T3, typename T4, typename T5,
145 typename T6>
146 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
147 const T5& p5, const T6& p6) {
148 new(space_) Type(p1, p2, p3, p4, p5, p6);
149 }
150
151 template <typename T1, typename T2, typename T3, typename T4, typename T5,
152 typename T6, typename T7>
153 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
154 const T5& p5, const T6& p6, const T7& p7) {
155 new(space_) Type(p1, p2, p3, p4, p5, p6, p7);
156 }
157
158 template <typename T1, typename T2, typename T3, typename T4, typename T5,
159 typename T6, typename T7, typename T8>
160 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
161 const T5& p5, const T6& p6, const T7& p7, const T8& p8) {
162 new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8);
163 }
164
165 template <typename T1, typename T2, typename T3, typename T4, typename T5,
166 typename T6, typename T7, typename T8, typename T9>
167 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
168 const T5& p5, const T6& p6, const T7& p7, const T8& p8,
169 const T9& p9) {
170 new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9);
171 }
172
173 template <typename T1, typename T2, typename T3, typename T4, typename T5,
174 typename T6, typename T7, typename T8, typename T9, typename T10>
175 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
176 const T5& p5, const T6& p6, const T7& p7, const T8& p8,
177 const T9& p9, const T10& p10) {
178 new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
179 }
180
181 template <typename T1, typename T2, typename T3, typename T4, typename T5,
182 typename T6, typename T7, typename T8, typename T9, typename T10,
183 typename T11>
184 inline void Init(const T1& p1, const T2& p2, const T3& p3, const T4& p4,
185 const T5& p5, const T6& p6, const T7& p7, const T8& p8,
186 const T9& p9, const T10& p10, const T11& p11) {
187 new(space_) Type(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11);
188 }
189
190 inline void Destroy() {
191 get()->~Type();
192 }
193
194 private:
Sameer Agarwaleb893402012-06-17 08:55:01 -0700195 CERES_ALIGNED_CHAR_ARRAY(Type, 1) space_;
Keir Mierle8ebb0732012-04-30 23:09:08 -0700196};
197
Sameer Agarwaleb893402012-06-17 08:55:01 -0700198#undef CERES_ALIGNED_CHAR_ARRAY
Keir Mierle8ebb0732012-04-30 23:09:08 -0700199
200} // namespace internal
201} // namespace ceres
202
203#endif // CERES_PUBLIC_INTERNAL_MANUAL_CONSTRUCTOR_H_