blob: 1ae1b96ae6e84bd3985e3426cb64291400e6a105 [file] [log] [blame]
jat@google.com134be542009-08-03 15:30:11 +00001#ifndef SCOPED_PTR_H
2#define SCOPED_PTR_H
3
4// (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
5// Copyright (c) 2001, 2002 Peter Dimov
6//
7// Permission is hereby granted, free of charge, to any person or organization
8// obtaining a copy of the software and accompanying documentation covered by
9// this license (the "Software") to use, reproduce, display, distribute,
10// execute, and transmit the Software, and to prepare derivative works of the
11// Software, and to permit third-parties to whom the Software is furnished to
12// do so, all subject to the following:
13//
14// The copyright notices in the Software and this entire statement, including
15// the above license grant, this restriction and the following disclaimer,
16// must be included in all copies of the Software, in whole or in part, and
17// all derivative works of the Software, unless such copies or derivative
18// works are solely in the form of machine-executable object code generated by
19// a source language processor.
20//
21// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27// DEALINGS IN THE SOFTWARE.
28//
29// See http://www.boost.org/libs/smart_ptr/scoped_ptr.htm for documentation.
30//
31//
32// scoped_ptr mimics a built-in pointer except that it guarantees deletion
33// of the object pointed to, either on destruction of the scoped_ptr or via
34// an explicit reset(). scoped_ptr is a simple solution for simple needs;
35// use shared_ptr if your needs are more complex.
36//
37// *** NOTE ***
38// If your scoped_ptr is a class member of class FOO pointing to a
39// forward declared type BAR (as shown below), then at creation (and
40// destruction) of an object of type FOO, BAR must be complete. You can do
41// this by either:
42// - Making all FOO constructors and destructors non-inlined to FOO's class
43// definition, instead placing them in foo.cc below an include of bar.h
44// - Including bar.h before any creation or destruction of any object of
45// type FOO
46// The former is probably the less error-prone method, as shown below.
47//
48// Example:
49//
50// -- foo.h --
51// class BAR;
52//
53// class FOO {
54// public:
55// FOO(); // Required for sources that instantiate class FOO to compile!
56// ~FOO(); // Required for sources that instantiate class FOO to compile!
57//
58// private:
59// scoped_ptr<BAR> bar_;
60// };
61//
62// -- foo.cc --
63// #include "bar.h"
64// #include "foo.h"
65// FOO::FOO() {} // Empty, but must be non-inlined to FOO's class definition.
66// FOO::~FOO() {} // Empty, but must be non-inlined to FOO's class definition.
67//
68// scoped_ptr_malloc added in by Ray Sidney of Google. When one of
69// these goes out of scope, instead of doing a delete or delete[], it
70// calls free(). scoped_ptr_malloc<char> is likely to see much more
71// use than any other specializations.
72//
73// release() added in by Spencer Kimball of Google. Use this to conditionally
74// transfer ownership of a heap-allocated object to the caller, usually on
75// method success.
76
77#include <cstddef> // for std::ptrdiff_t
78#include <assert.h> // for assert
79#include <stdlib.h> // for free() decl
80
81template <typename T>
82class scoped_ptr;
83
84template <typename T>
85class scoped_ptr {
86 private:
87
88 T* ptr;
89
90 // scoped_ptr's must not be copied. We make sure of that by making the
91 // copy constructor prototype private. At the same time, there is no body
92 // for this constructor. Thus, if anything that has access to private
93 // members of scoped_ptr ever (inadvertently) copies a scoped_ptr, the
94 // linker will complain about missing symbols. This is a good thing!
95 scoped_ptr(scoped_ptr const &);
96 scoped_ptr & operator=(scoped_ptr const &);
97
98 public:
99
100 typedef T element_type;
101
102 explicit scoped_ptr(T* p = 0): ptr(p) {}
103
104 ~scoped_ptr() {
105 typedef char type_must_be_complete[sizeof(T)];
106 delete ptr;
107 }
108
109 void reset(T* p = 0) {
110 typedef char type_must_be_complete[sizeof(T)];
111
112 if (ptr != p) {
113 delete ptr;
114 ptr = p;
115 }
116 }
117
118 T& operator*() const {
119 assert(ptr != 0);
120 return *ptr;
121 }
122
123 T* operator->() const {
124 assert(ptr != 0);
125 return ptr;
126 }
127
128 bool operator==(T* p) const {
129 return ptr == p;
130 }
131
132 bool operator!=(T* p) const {
133 return ptr != p;
134 }
135
136 T* get() const {
137 return ptr;
138 }
139
140 void swap(scoped_ptr & b) {
141 T* tmp = b.ptr;
142 b.ptr = ptr;
143 ptr = tmp;
144 }
145
146 T* release() {
147 T* tmp = ptr;
148 ptr = 0;
149 return tmp;
150 }
151
152 private:
153
154 // no reason to use these: each scoped_ptr should have its own object
155 template <typename U> bool operator==(scoped_ptr<U> const& p) const;
156 template <typename U> bool operator!=(scoped_ptr<U> const& p) const;
157};
158
159template<typename T> inline
160void swap(scoped_ptr<T>& a, scoped_ptr<T>& b) {
161 a.swap(b);
162}
163
164template<typename T> inline
165bool operator==(T* p, const scoped_ptr<T>& b) {
166 return p == b.get();
167}
168
169template<typename T> inline
170bool operator!=(T* p, const scoped_ptr<T>& b) {
171 return p != b.get();
172}
173
174// scoped_array extends scoped_ptr to arrays. Deletion of the array pointed to
175// is guaranteed, either on destruction of the scoped_array or via an explicit
176// reset(). Use shared_array or std::vector if your needs are more complex.
177
178template<typename T>
179class scoped_array {
180 private:
181
182 T* ptr;
183
184 scoped_array(scoped_array const &);
185 scoped_array & operator=(scoped_array const &);
186
187 public:
188
189 typedef T element_type;
190
191 explicit scoped_array(T* p = 0) : ptr(p) {}
192
193 ~scoped_array() {
194 typedef char type_must_be_complete[sizeof(T)];
195 delete[] ptr;
196 }
197
198 void reset(T* p = 0) {
199 typedef char type_must_be_complete[sizeof(T)];
200
201 if (ptr != p) {
202 delete [] ptr;
203 ptr = p;
204 }
205 }
206
207 T& operator[](std::ptrdiff_t i) const {
208 assert(ptr != 0);
209 assert(i >= 0);
210 return ptr[i];
211 }
212
213 bool operator==(T* p) const {
214 return ptr == p;
215 }
216
217 bool operator!=(T* p) const {
218 return ptr != p;
219 }
220
221 T* get() const {
222 return ptr;
223 }
224
225 void swap(scoped_array & b) {
226 T* tmp = b.ptr;
227 b.ptr = ptr;
228 ptr = tmp;
229 }
230
231 T* release() {
232 T* tmp = ptr;
233 ptr = 0;
234 return tmp;
235 }
236
237 private:
238
239 // no reason to use these: each scoped_array should have its own object
240 template <typename U> bool operator==(scoped_array<U> const& p) const;
241 template <typename U> bool operator!=(scoped_array<U> const& p) const;
242};
243
244template<class T> inline
245void swap(scoped_array<T>& a, scoped_array<T>& b) {
246 a.swap(b);
247}
248
249template<typename T> inline
250bool operator==(T* p, const scoped_array<T>& b) {
251 return p == b.get();
252}
253
254template<typename T> inline
255bool operator!=(T* p, const scoped_array<T>& b) {
256 return p != b.get();
257}
258
259
260// This class wraps the c library function free() in a class that can be
261// passed as a template argument to scoped_ptr_malloc below.
262class ScopedPtrMallocFree {
263 public:
264 inline void operator()(void* x) const {
265 free(x);
266 }
267};
268
269// scoped_ptr_malloc<> is similar to scoped_ptr<>, but it accepts a
270// second template argument, the functor used to free the object.
271
272template<typename T, typename FreeProc = ScopedPtrMallocFree>
273class scoped_ptr_malloc {
274 private:
275
276 T* ptr;
277
278 scoped_ptr_malloc(scoped_ptr_malloc const &);
279 scoped_ptr_malloc & operator=(scoped_ptr_malloc const &);
280
281 public:
282
283 typedef T element_type;
284
285 explicit scoped_ptr_malloc(T* p = 0): ptr(p) {}
286
287 ~scoped_ptr_malloc() {
288 typedef char type_must_be_complete[sizeof(T)];
289 free_((void*) ptr);
290 }
291
292 void reset(T* p = 0) {
293 typedef char type_must_be_complete[sizeof(T)];
294
295 if (ptr != p) {
296 free_((void*) ptr);
297 ptr = p;
298 }
299 }
300
301 T& operator*() const {
302 assert(ptr != 0);
303 return *ptr;
304 }
305
306 T* operator->() const {
307 assert(ptr != 0);
308 return ptr;
309 }
310
311 bool operator==(T* p) const {
312 return ptr == p;
313 }
314
315 bool operator!=(T* p) const {
316 return ptr != p;
317 }
318
319 T* get() const {
320 return ptr;
321 }
322
323 void swap(scoped_ptr_malloc & b) {
324 T* tmp = b.ptr;
325 b.ptr = ptr;
326 ptr = tmp;
327 }
328
329 T* release() {
330 T* tmp = ptr;
331 ptr = 0;
332 return tmp;
333 }
334
335 private:
336
337 // no reason to use these: each scoped_ptr_malloc should have its own object
338 template <typename U, typename GP>
339 bool operator==(scoped_ptr_malloc<U, GP> const& p) const;
340 template <typename U, typename GP>
341 bool operator!=(scoped_ptr_malloc<U, GP> const& p) const;
342
343 static FreeProc const free_;
344};
345
346template<typename T, typename FP>
347FP const scoped_ptr_malloc<T,FP>::free_ = FP();
348
349template<typename T, typename FP> inline
350void swap(scoped_ptr_malloc<T,FP>& a, scoped_ptr_malloc<T,FP>& b) {
351 a.swap(b);
352}
353
354template<typename T, typename FP> inline
355bool operator==(T* p, const scoped_ptr_malloc<T,FP>& b) {
356 return p == b.get();
357}
358
359template<typename T, typename FP> inline
360bool operator!=(T* p, const scoped_ptr_malloc<T,FP>& b) {
361 return p != b.get();
362}
363
364#endif // #ifndef SCOPED_PTR_H