Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(653)

Side by Side Diff: base/memory/scoped_ptr.h

Issue 11149006: Extend scoped_ptr to be closer to unique_ptr. Support custom deleters, and deleting arrays. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Element[] added, comments cleaned. One friend issue fixed. Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | base/memory/scoped_ptr_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Scopers help you manage ownership of a pointer, helping you easily manage the 5 // Scopers help you manage ownership of a pointer, helping you easily manage the
6 // a pointer within a scope, and automatically destroying the pointer at the 6 // a pointer within a scope, and automatically destroying the pointer at the
7 // end of a scope. There are two main classes you will use, which correspond 7 // end of a scope. There are two main classes you will use, which correspond
8 // to the operators new/delete and new[]/delete[]. 8 // to the operators new/delete and new[]/delete[].
9 // 9 //
10 // Example usage (scoped_ptr): 10 // Example usage (scoped_ptr):
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 #define BASE_MEMORY_SCOPED_PTR_H_ 88 #define BASE_MEMORY_SCOPED_PTR_H_
89 89
90 // This is an implementation designed to match the anticipated future TR2 90 // This is an implementation designed to match the anticipated future TR2
91 // implementation of the scoped_ptr class, and its closely-related brethren, 91 // implementation of the scoped_ptr class, and its closely-related brethren,
92 // scoped_array, scoped_ptr_malloc. 92 // scoped_array, scoped_ptr_malloc.
93 93
94 #include <assert.h> 94 #include <assert.h>
95 #include <stddef.h> 95 #include <stddef.h>
96 #include <stdlib.h> 96 #include <stdlib.h>
97 97
98 #include <utility>
99
98 #include "base/basictypes.h" 100 #include "base/basictypes.h"
99 #include "base/compiler_specific.h" 101 #include "base/compiler_specific.h"
100 #include "base/move.h" 102 #include "base/move.h"
101 #include "base/template_util.h" 103 #include "base/template_util.h"
102 104
103 namespace base { 105 namespace base {
104 106
105 namespace subtle { 107 namespace subtle {
106 class RefCountedBase; 108 class RefCountedBase;
107 class RefCountedThreadSafeBase; 109 class RefCountedThreadSafeBase;
108 } // namespace subtle 110 } // namespace subtle
109 111
112 // Function object which deletes its parameter, which must be a pointer.
113 // If C is an array type, invokes 'delete[]' on the parameter; otherwise,
114 // invokes 'delete'. The default deleter for scoped_ptr<T>.
115 template <class C>
116 struct DefaultDeleter {
117 DefaultDeleter() {}
118 template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) {
119 // All default single-object deleters can trivially convert to one another.
120 }
121 inline void operator()(C* ptr) const {
122 enum { type_must_be_complete = sizeof(C) };
123 delete ptr;
124 }
125 };
126
127 // Specialization of DefaultDeleter for array types.
128 template <class C>
129 struct DefaultDeleter<C[]> {
130 inline void operator()(C* ptr) const {
131 enum { type_must_be_complete = sizeof(C) };
132 delete[] ptr;
133 }
134
135 private:
136 // Disable this operator for any U != C because it is unsafe to execute
137 // an array delete when the static type of the array mismatches the dynamic
138 // type.
139 template <typename U> void operator()(U* array) const;
140 };
141
142 // Function object which invokes 'free' on its parameter, which must be
143 // a pointer. Can be used to store malloc-allocated pointers in scoped_ptr:
144 //
145 // scoped_ptr<int, base::FreeDeleter> foo_ptr(
146 // static_cast<int>(malloc(sizeof(int))));
147 struct FreeDeleter {
148 inline void operator()(void* ptr) const {
149 free(ptr);
150 }
151 };
152
110 namespace internal { 153 namespace internal {
111 154
112 template <typename T> struct IsNotRefCounted { 155 template <typename T> struct IsNotRefCounted {
113 enum { 156 enum {
114 value = !base::is_convertible<T*, base::subtle::RefCountedBase*>::value && 157 value = !base::is_convertible<T*, base::subtle::RefCountedBase*>::value &&
115 !base::is_convertible<T*, base::subtle::RefCountedThreadSafeBase*>:: 158 !base::is_convertible<T*, base::subtle::RefCountedThreadSafeBase*>::
116 value 159 value
117 }; 160 };
118 }; 161 };
119 162
163 // Minimal implementation of the core logic of scoped_ptr, suitable for
164 // reuse in both scoped_ptr and its specialization.
165 template <class Element, class Deleter>
Ryan Sleevi 2012/10/18 03:17:10 Why not keep the naming consistent with std::, in
awong 2012/10/18 18:08:02 I don't have a strong preference. We already have
gromer 2012/10/18 20:45:20 Note that unique_ptr has element_type and deleter_
awong 2012/11/27 22:36:16 Went back to T and D.
166 class scoped_ptr_impl {
167 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr_impl, RValue)
168
169 public:
170 explicit scoped_ptr_impl(Element* p) : data_(p) { }
171
172 template <typename U, typename V>
173 scoped_ptr_impl(scoped_ptr_impl<U, V> other) : data_(NULL) {
174 // TODO(ajwong): This needs to respect move only deleters rather than doing
175 // a copy to be consistent with unique_ptr. But we don't have a general
176 // "move()" function. Do I need to use SFINAE to make this work? Or should
Jeffrey Yasskin 2012/10/18 04:14:29 I'd like to get a general move() function, which c
awong 2012/10/18 18:08:02 It could be useful in specifically this situation.
177 // I modify how RValue works so we have a base::subtle::move() with a
178 // base::suble::rvalue<> template rather than a private RValue struct?
179 reset(other.release());
180 get_deleter() = other.get_deleter();
Ryan Sleevi 2012/10/18 03:17:10 So I'm not misreading - you're intentionally relyi
awong 2012/10/18 18:08:02 Yep. Credit gromer@.
181 }
182
183 template <typename U, typename V>
184 const scoped_ptr_impl& operator=(scoped_ptr_impl<U, V> rhs) {
185 // TODO(ajwong): Same problem as in the constructor above.
186 reset(rhs.release());
187 get_deleter() = rhs.get_deleter();
188 return *this;
189 }
190
191 scoped_ptr_impl(RValue rvalue) : data_(NULL) {
192 swap(*rvalue.object);
193 }
194
195 ~scoped_ptr_impl() {
196 if (data_.ptr != NULL) {
197 get_deleter()(data_.ptr);
198 }
199 }
200
201 void reset(Element* p) {
202 // This self-reset check is deprecated.
203 // this->reset(this->get()) currently works, but it is DEPRECATED, and
204 // will be removed once we verify that no one depends on it.
205 //
206 // TODO(ajwong): File bug for the deprecation and ordering issue below.
207 if (p != data_.ptr) {
208 if (data_.ptr != NULL) {
209 // Note that this can lead to undefined behavior and memory leaks
210 // in the unlikely but possible case that get_deleter()(get())
211 // indirectly deletes this. The fix is to reset ptr_ before deleting
212 // its old value, but first we need to clean up the code that relies
213 // on the current sequencing.
214 get_deleter()(data_.ptr);
215 }
216 data_.ptr = p;
217 }
218 }
219
220 Element* get() const { return data_.ptr; }
221
222 Deleter& get_deleter() { return data_; }
223 const Deleter& get_deleter() const { return data_; }
224
225 void swap(scoped_ptr_impl& p2) {
226 // Standard swap idiom: 'using std::swap' ensures that std::swap is
227 // present in the overload set, but we call swap unqualified so that
228 // any more-specific overloads can be used, if available.
229 using std::swap;
Ryan Sleevi 2012/10/18 03:17:10 I seem to recall (and of course, without citable r
Jeffrey Yasskin 2012/10/18 04:14:29 Yep. swap methods that people want found need to b
230 swap(static_cast<Deleter&>(data_), static_cast<Deleter&>(p2.data_));
231 swap(data_.ptr, p2.data_.ptr);
232 }
233
234 Element* release() {
235 Element* retVal = data_.ptr;
236 data_.ptr = NULL;
237 return retVal;
238 }
239
240 private:
241 // Needed to allow type-converting constructor.
242 template <typename U, typename V> friend class scoped_ptr_impl;
Ryan Sleevi 2012/10/18 03:17:10 I didn't think MSVC let you get away with this.
awong 2012/10/18 18:08:02 Okay, will test. Worst case, I just merge scoped_p
243
244 // Use the empty base class optimization to allow us to have a Deleter
245 // member, while avoiding any space overhead for it when Deleter is an
246 // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
247 // discussion of this technique.
248 struct Data : public Deleter {
249 explicit Data(Element* ptr_in) : ptr(ptr_in) {}
250 Element* ptr;
251 };
252
253 Data data_;
254 };
255
120 } // namespace internal 256 } // namespace internal
257
121 } // namespace base 258 } // namespace base
122 259
123 // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> 260 // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
124 // automatically deletes the pointer it holds (if any). 261 // automatically deletes the pointer it holds (if any).
125 // That is, scoped_ptr<T> owns the T object that it points to. 262 // That is, scoped_ptr<T> owns the T object that it points to.
126 // Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object. 263 // Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
127 // Also like T*, scoped_ptr<T> is thread-compatible, and once you 264 // Also like T*, scoped_ptr<T> is thread-compatible, and once you
128 // dereference it, you get the thread safety guarantees of T. 265 // dereference it, you get the thread safety guarantees of T.
129 // 266 //
130 // The size of a scoped_ptr is small: 267 // The size of a scoped_ptr is small:
131 // sizeof(scoped_ptr<C>) == sizeof(C*) 268 // sizeof(scoped_ptr<C>) == sizeof(C*)
132 template <class C> 269 template <class Element, class Deleter = base::DefaultDeleter<Element> >
133 class scoped_ptr { 270 class scoped_ptr {
134 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) 271 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
135 272
136 COMPILE_ASSERT(base::internal::IsNotRefCounted<C>::value, 273 COMPILE_ASSERT(base::internal::IsNotRefCounted<Element>::value,
137 C_is_refcounted_type_and_needs_scoped_refptr); 274 Element_is_refcounted_type_and_needs_scoped_refptr);
138 275
139 public: 276 public:
140 277 // The element and deleter types.
141 // The element type 278 typedef Element element_type;
142 typedef C element_type; 279 typedef Deleter deleter_type;
143 280
144 // Constructor. Defaults to initializing with NULL. 281 // Constructor. Defaults to initializing with NULL.
145 // There is no way to create an uninitialized scoped_ptr. 282 // There is no way to create an uninitialized scoped_ptr.
146 // The input parameter must be allocated with new. 283 //
147 explicit scoped_ptr(C* p = NULL) : ptr_(p) { } 284 // TODO(ajwong): REVIEWER QUESTION: is it work breaking out the default
285 // constructor here, and a 0-arity reset() function below to get rid of the
286 // default arguments?
287 explicit scoped_ptr(element_type* p = NULL) : impl_(p) { }
Ryan Sleevi 2012/10/18 03:17:10 This is the ONE place that I actually like default
Jeffrey Yasskin 2012/10/18 04:14:29 Yeah. Meh on my part.
awong 2012/10/18 18:08:02 I guess I'll stick with the style guide. The C++ r
gromer 2012/10/18 20:45:20 FWIW the standard specifies the 0- and 1-arg const
awong 2012/11/27 22:36:16 All the more reason to avoid default arguments :-/
148 288
149 // Constructor. Allows construction from a scoped_ptr rvalue for a 289 // Constructor. Allows construction from a scoped_ptr rvalue for a
150 // convertible type. 290 // convertible type and deleter.
151 template <typename U> 291 template <typename U, typename V>
152 scoped_ptr(scoped_ptr<U> other) : ptr_(other.release()) { } 292 scoped_ptr(scoped_ptr<U, V> other) : impl_(other.impl_.Pass()) { }
153 293
154 // Constructor. Move constructor for C++03 move emulation of this type. 294 // Constructor. Move constructor for C++03 move emulation of this type.
155 scoped_ptr(RValue rvalue) 295 //
156 : ptr_(rvalue.object->release()) { 296 // TODO(ajwong): REVIEWER QUESTION: is it cleaner to use the swap() idiom?
Jeffrey Yasskin 2012/10/18 04:14:29 The "swap idiom" means to me the operator= techniq
awong 2012/10/18 18:08:02 Yes, I was thinking exactly scoped_ptr(RValue rva
Jeffrey Yasskin 2012/10/18 18:33:45 I somewhat prefer the current implementation.
awong 2012/11/27 22:36:16 Done.
157 } 297 scoped_ptr(RValue rvalue) : impl_(rvalue.object->release()) { }
158
159 // Destructor. If there is a C object, delete it.
160 // We don't need to test ptr_ == NULL because C++ does that for us.
161 ~scoped_ptr() {
162 enum { type_must_be_complete = sizeof(C) };
163 delete ptr_;
164 }
165 298
166 // operator=. Allows assignment from a scoped_ptr rvalue for a convertible 299 // operator=. Allows assignment from a scoped_ptr rvalue for a convertible
167 // type. 300 // type and deleter.
168 template <typename U> 301 template <typename U, typename V>
169 scoped_ptr& operator=(scoped_ptr<U> rhs) { 302 scoped_ptr& operator=(scoped_ptr<U, V> rhs) {
170 reset(rhs.release()); 303 impl_ = rhs.impl_.Pass();
171 return *this; 304 return *this;
172 } 305 }
173 306
174 // operator=. Move operator= for C++03 move emulation of this type. 307 // operator=. Move operator= for C++03 move emulation of this type.
175 scoped_ptr& operator=(RValue rhs) { 308 scoped_ptr& operator=(RValue rhs) {
176 swap(*rhs->object); 309 swap(*rhs->object);
177 return *this; 310 return *this;
178 } 311 }
179 312
180 // Reset. Deletes the current owned object, if any. 313 // Reset. Deletes the current owned object, if any.
181 // Then takes ownership of a new object, if given. 314 // Then takes ownership of a new object, if given.
182 // this->reset(this->get()) works. 315 void reset(element_type* p = NULL) {
183 void reset(C* p = NULL) { 316 impl_.reset(p);
184 if (p != ptr_) {
185 enum { type_must_be_complete = sizeof(C) };
186 delete ptr_;
187 ptr_ = p;
188 }
189 } 317 }
190 318
191 // Accessors to get the owned object. 319 // Accessors to get the owned object.
192 // operator* and operator-> will assert() if there is no current object. 320 // operator* and operator-> will assert() if there is no current object.
193 C& operator*() const { 321 element_type& operator*() const {
194 assert(ptr_ != NULL); 322 assert(impl_.get() != NULL);
195 return *ptr_; 323 return *impl_.get();
196 } 324 }
197 C* operator->() const { 325 element_type* operator->() const {
198 assert(ptr_ != NULL); 326 assert(impl_.get() != NULL);
199 return ptr_; 327 return impl_.get();
200 } 328 }
201 C* get() const { return ptr_; } 329 element_type* get() const { return impl_.get(); }
202 330
203 // Allow scoped_ptr<C> to be used in boolean expressions, but not 331 // Access to the deleter.
332 deleter_type& get_deleter() { return impl_.get_deleter(); }
333 const deleter_type& get_deleter() const { return impl_.get_deleter(); }
334
335 // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
204 // implicitly convertible to a real bool (which is dangerous). 336 // implicitly convertible to a real bool (which is dangerous).
205 typedef C* scoped_ptr::*Testable; 337 typedef element_type* scoped_ptr::*Testable;
206 operator Testable() const { return ptr_ ? &scoped_ptr::ptr_ : NULL; } 338 operator Testable() const { return impl_.get() ? &impl_.get() : NULL; }
207 339
208 // Comparison operators. 340 // Comparison operators.
209 // These return whether two scoped_ptr refer to the same object, not just to 341 // These return whether two scoped_ptr refer to the same object, not just to
210 // two different but equal objects. 342 // two different but equal objects.
211 bool operator==(C* p) const { return ptr_ == p; } 343 bool operator==(element_type* p) const { return impl_.get() == p; }
212 bool operator!=(C* p) const { return ptr_ != p; } 344 bool operator!=(element_type* p) const { return impl_.get() != p; }
213 345
214 // Swap two scoped pointers. 346 // Swap two scoped pointers.
215 void swap(scoped_ptr& p2) { 347 void swap(scoped_ptr& p2) {
216 C* tmp = ptr_; 348 impl_.swap(p2.impl_);
217 ptr_ = p2.ptr_;
218 p2.ptr_ = tmp;
219 } 349 }
220 350
221 // Release a pointer. 351 // Release a pointer.
222 // The return value is the current pointer held by this object. 352 // The return value is the current pointer held by this object.
223 // If this object holds a NULL pointer, the return value is NULL. 353 // If this object holds a NULL pointer, the return value is NULL.
224 // After this operation, this object will hold a NULL pointer, 354 // After this operation, this object will hold a NULL pointer,
225 // and will not own the object any more. 355 // and will not own the object any more.
226 C* release() WARN_UNUSED_RESULT { 356 element_type* release() WARN_UNUSED_RESULT {
227 C* retVal = ptr_; 357 return impl_.release();
228 ptr_ = NULL;
229 return retVal;
230 } 358 }
231 359
232 template <typename PassAsType> 360 template <typename PassAsType,
233 scoped_ptr<PassAsType> PassAs() { 361 typename PasAsDeleter = base::DefaultDeleter<PassAsType> >
234 return scoped_ptr<PassAsType>(release()); 362 scoped_ptr<PassAsType, PasAsDeleter> PassAs() {
Ryan Sleevi 2012/10/18 03:17:10 Did you accidentally an S? ( Pas*s*AsDeleter )
awong 2012/10/18 18:08:02 heh...yes I did. But I also just had to remove del
363 return scoped_ptr<PassAsType, PasAsDeleter>(Pass());
235 } 364 }
236 365
237 private: 366 private:
238 C* ptr_; 367 // Needed to reach into |impl_| in the constructor.
368 template <typename U, typename V> friend class scoped_ptr;
369 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
239 370
240 // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't 371 // Forbid comparison of scoped_ptr types. If U != Element, it totally
241 // make sense, and if C2 == C, it still doesn't make sense because you should 372 // doesn't make sense, and if U == Element, it still doesn't make sense
242 // never have the same object owned by two different scoped_ptrs. 373 // because you should never have the same object owned by two different
243 template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; 374 // scoped_ptrs.
244 template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; 375 template <class U> bool operator==(scoped_ptr<U> const& p2) const;
376 template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
377 };
245 378
379 template <class Element, class Deleter>
380 class scoped_ptr<Element[], Deleter> {
381 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
382
383 COMPILE_ASSERT(base::internal::IsNotRefCounted<Element>::value,
384 Element_is_refcounted_type_and_needs_scoped_refptr);
385
386 public:
387 // The element and deleter types.
388 typedef Element element_type;
389 typedef Deleter deleter_type;
390
391 // Constructor. Defaults to initializing with NULL.
392 // There is no way to create an uninitialized scoped_ptr.
Ryan Sleevi 2012/10/18 03:17:10 line 392 seems superflous
awong 2012/10/18 18:08:02 Yeah. It was just keeping in line with the old imp
393 scoped_ptr() : impl_(NULL) { }
394
395 // Constructor. Stores the given array. Note that the argument's type
396 // must exactly match Element*. In particular:
397 // - it cannot be a pointer to a type derived from Element, because it is
398 // inherently unsafe to access an array through a pointer whose
Jeffrey Yasskin 2012/10/18 04:14:29 There's vague wording on subscripting at [expr.add
awong 2012/10/18 18:08:02 Let me ask gromer@ for pointers. This is really hi
gromer 2012/10/18 20:45:20 From [basic.compound]p3: "If an object of type T i
awong 2012/11/27 22:36:16 I don't think I understand this quite enough to wr
399 // dynamic type does not match its static type. If you're doing this,
400 // fix your code.
401 // - it cannot be NULL, because NULL is an integral expression, not a
402 // pointer to Element. Use the no-argument version instead of explicitly
403 // passing NULL.
404 // - it cannot be const-qualified differently from Element. You can work
Jeffrey Yasskin 2012/10/18 04:14:29 Interesting. What goes wrong with this?
awong 2012/10/18 18:08:02 Will ask gromer@
gromer 2012/10/18 20:45:20 Nothing; it's perfectly safe, but forbidden by uni
willchan no longer on Chromium 2012/10/18 21:28:42 We actually do hope to switch to using unique_ptr
awong 2012/11/27 22:36:16 I added the citation, and removed the reference to
405 // around this using implicit_cast (from base/casts.h):
406 //
407 // int* i;
408 // scoped_ptr<const int[]> arr(implicit_cast<const int[]>(i));
409 //
410 // TODO(ajwong): Find citations for the above. Also see if we want to keep
411 // the implicit_cast<> comment.
412 explicit scoped_ptr(element_type* array = NULL) : impl_(array) { }
413
414 // Constructor. Move constructor for C++03 move emulation of this type.
415 //
416 // TODO(ajwong): reviewer question: is it cleaner to use the swap() idiom?
417 scoped_ptr(RValue rvalue) : impl_(rvalue.object->release()) { }
418
419 // operator=. Move operator= for C++03 move emulation of this type.
420 scoped_ptr& operator=(RValue rhs) {
421 swap(*rhs->object);
422 return *this;
423 }
424
425 // Reset. Deletes the current owned object, if any.
426 // Then takes ownership of a new object, if given.
427 void reset(element_type* array = NULL) {
428 impl_.reset(array);
429 }
430
431 // Accessors to get the owned object.
432 // operator* and operator-> will assert() if there is no current object.
433 element_type& operator[](size_t i) const {
434 assert(impl_.get() != NULL);
435 return impl_.get()[i];
436 }
437 element_type* get() const { return impl_.get(); }
438
439 // Access to the deleter.
440 deleter_type& get_deleter() { return impl_.get_deleter(); }
441 const deleter_type& get_deleter() const { return impl_.get_deleter(); }
442
443 // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
444 // implicitly convertible to a real bool (which is dangerous).
445 typedef element_type* scoped_ptr::*Testable;
446 operator Testable() const { return impl_.get() ? &impl_.get() : NULL; }
447
448 // Comparison operators.
449 // These return whether two scoped_ptr refer to the same object, not just to
450 // two different but equal objects.
451 bool operator==(element_type* array) const { return impl_.get() == array; }
452 bool operator!=(element_type* array) const { return impl_.get() != array; }
453
454 // Swap two scoped pointers.
455 void swap(scoped_ptr& p2) {
456 impl_.swap(p2.impl_);
457 }
458
459 // Release a pointer.
460 // The return value is the current pointer held by this object.
461 // If this object holds a NULL pointer, the return value is NULL.
462 // After this operation, this object will hold a NULL pointer,
463 // and will not own the object any more.
464 element_type* release() WARN_UNUSED_RESULT {
465 return impl_.release();
466 }
467
468 private:
469 // Force element_type to be a complete type.
470 enum { type_must_be_complete = sizeof(element_type) };
471
472 // Actually hold the data.
473 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
474
475 // Disable initialization from any type other than element_type*, by
476 // providing a constructor that matches such an initialization, but is
477 // private and has no definition. This is disabled because it is not safe to
478 // call delete[] on an array whose static type does not match its dynamic
479 // type.
480 template <typename T>
481 explicit scoped_ptr(T* array);
482
483 // Disable reset() from any type other than element_type*, for the same
484 // reasons as the constructor above.
485 template <typename T>
486 void reset(T* array);
487
488 // Forbid comparison of scoped_ptr types. If U != Element, it totally
489 // doesn't make sense, and if U == Element, it still doesn't make sense
490 // because you should never have the same object owned by two different
491 // scoped_ptrs.
492 template <class U> bool operator==(scoped_ptr<U> const& p2) const;
493 template <class U> bool operator!=(scoped_ptr<U> const& p2) const;
246 }; 494 };
247 495
248 // Free functions 496 // Free functions
249 template <class C> 497 template <class C, class D>
250 void swap(scoped_ptr<C>& p1, scoped_ptr<C>& p2) { 498 void swap(scoped_ptr<C, D>& p1, scoped_ptr<C, D>& p2) {
251 p1.swap(p2); 499 p1.swap(p2);
252 } 500 }
253 501
254 template <class C> 502 template <class C, class D>
255 bool operator==(C* p1, const scoped_ptr<C>& p2) { 503 bool operator==(C* p1, const scoped_ptr<C, D>& p2) {
256 return p1 == p2.get(); 504 return p1 == p2.get();
257 } 505 }
258 506
259 template <class C> 507 template <class C, class D>
260 bool operator!=(C* p1, const scoped_ptr<C>& p2) { 508 bool operator!=(C* p1, const scoped_ptr<C, D>& p2) {
261 return p1 != p2.get(); 509 return p1 != p2.get();
262 } 510 }
263 511
264 // scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate 512 // scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate
265 // with new [] and the destructor deletes objects with delete []. 513 // with new [] and the destructor deletes objects with delete [].
266 // 514 //
267 // As with scoped_ptr<C>, a scoped_array<C> either points to an object 515 // As with scoped_ptr<C>, a scoped_array<C> either points to an object
268 // or is NULL. A scoped_array<C> owns the object that it points to. 516 // or is NULL. A scoped_array<C> owns the object that it points to.
269 // scoped_array<T> is thread-compatible, and once you index into it, 517 // scoped_array<T> is thread-compatible, and once you index into it,
270 // the returned objects have only the thread safety guarantees of T. 518 // the returned objects have only the thread safety guarantees of T.
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
515 763
516 // A function to convert T* into scoped_ptr<T> 764 // A function to convert T* into scoped_ptr<T>
517 // Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation 765 // Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation
518 // for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg)) 766 // for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
519 template <typename T> 767 template <typename T>
520 scoped_ptr<T> make_scoped_ptr(T* ptr) { 768 scoped_ptr<T> make_scoped_ptr(T* ptr) {
521 return scoped_ptr<T>(ptr); 769 return scoped_ptr<T>(ptr);
522 } 770 }
523 771
524 #endif // BASE_MEMORY_SCOPED_PTR_H_ 772 #endif // BASE_MEMORY_SCOPED_PTR_H_
OLDNEW
« no previous file with comments | « no previous file | base/memory/scoped_ptr_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698