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

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

Issue 603353005: Revert of Add nullptr support to scoped_ptr. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 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
« 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 a 5 // Scopers help you manage ownership of a pointer, helping you easily manage a
6 // pointer within a scope, and automatically destroying the pointer at the end 6 // pointer within a scope, and automatically destroying the pointer at the end
7 // of a scope. There are two main classes you will use, which correspond to the 7 // of a scope. There are two main classes you will use, which correspond to the
8 // operators new/delete and new[]/delete[]. 8 // operators new/delete and new[]/delete[].
9 // 9 //
10 // Example usage (scoped_ptr<T>): 10 // Example usage (scoped_ptr<T>):
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
51 // } 51 // }
52 // scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) { 52 // scoped_ptr<Foo> PassThru(scoped_ptr<Foo> arg) {
53 // return arg.Pass(); 53 // return arg.Pass();
54 // } 54 // }
55 // 55 //
56 // { 56 // {
57 // scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay"). 57 // scoped_ptr<Foo> ptr(new Foo("yay")); // ptr manages Foo("yay").
58 // TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay"). 58 // TakesOwnership(ptr.Pass()); // ptr no longer owns Foo("yay").
59 // scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo. 59 // scoped_ptr<Foo> ptr2 = CreateFoo(); // ptr2 owns the return Foo.
60 // scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2. 60 // scoped_ptr<Foo> ptr3 = // ptr3 now owns what was in ptr2.
61 // PassThru(ptr2.Pass()); // ptr2 is correspondingly nullptr. 61 // PassThru(ptr2.Pass()); // ptr2 is correspondingly NULL.
62 // } 62 // }
63 // 63 //
64 // Notice that if you do not call Pass() when returning from PassThru(), or 64 // Notice that if you do not call Pass() when returning from PassThru(), or
65 // when invoking TakesOwnership(), the code will not compile because scopers 65 // when invoking TakesOwnership(), the code will not compile because scopers
66 // are not copyable; they only implement move semantics which require calling 66 // are not copyable; they only implement move semantics which require calling
67 // the Pass() function to signify a destructive transfer of state. CreateFoo() 67 // the Pass() function to signify a destructive transfer of state. CreateFoo()
68 // is different though because we are constructing a temporary on the return 68 // is different though because we are constructing a temporary on the return
69 // line and thus can avoid needing to call Pass(). 69 // line and thus can avoid needing to call Pass().
70 // 70 //
71 // Pass() properly handles upcast in initialization, i.e. you can use a 71 // Pass() properly handles upcast in initialization, i.e. you can use a
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 !base::is_convertible<T*, base::subtle::RefCountedThreadSafeBase*>:: 182 !base::is_convertible<T*, base::subtle::RefCountedThreadSafeBase*>::
183 value 183 value
184 }; 184 };
185 }; 185 };
186 186
187 // Minimal implementation of the core logic of scoped_ptr, suitable for 187 // Minimal implementation of the core logic of scoped_ptr, suitable for
188 // reuse in both scoped_ptr and its specializations. 188 // reuse in both scoped_ptr and its specializations.
189 template <class T, class D> 189 template <class T, class D>
190 class scoped_ptr_impl { 190 class scoped_ptr_impl {
191 public: 191 public:
192 explicit scoped_ptr_impl(T* p) : data_(p) {} 192 explicit scoped_ptr_impl(T* p) : data_(p) { }
193 193
194 // Initializer for deleters that have data parameters. 194 // Initializer for deleters that have data parameters.
195 scoped_ptr_impl(T* p, const D& d) : data_(p, d) {} 195 scoped_ptr_impl(T* p, const D& d) : data_(p, d) {}
196 196
197 // Templated constructor that destructively takes the value from another 197 // Templated constructor that destructively takes the value from another
198 // scoped_ptr_impl. 198 // scoped_ptr_impl.
199 template <typename U, typename V> 199 template <typename U, typename V>
200 scoped_ptr_impl(scoped_ptr_impl<U, V>* other) 200 scoped_ptr_impl(scoped_ptr_impl<U, V>* other)
201 : data_(other->release(), other->get_deleter()) { 201 : data_(other->release(), other->get_deleter()) {
202 // We do not support move-only deleters. We could modify our move 202 // We do not support move-only deleters. We could modify our move
203 // emulation to have base::subtle::move() and base::subtle::forward() 203 // emulation to have base::subtle::move() and base::subtle::forward()
204 // functions that are imperfect emulations of their C++11 equivalents, 204 // functions that are imperfect emulations of their C++11 equivalents,
205 // but until there's a requirement, just assume deleters are copyable. 205 // but until there's a requirement, just assume deleters are copyable.
206 } 206 }
207 207
208 template <typename U, typename V> 208 template <typename U, typename V>
209 void TakeState(scoped_ptr_impl<U, V>* other) { 209 void TakeState(scoped_ptr_impl<U, V>* other) {
210 // See comment in templated constructor above regarding lack of support 210 // See comment in templated constructor above regarding lack of support
211 // for move-only deleters. 211 // for move-only deleters.
212 reset(other->release()); 212 reset(other->release());
213 get_deleter() = other->get_deleter(); 213 get_deleter() = other->get_deleter();
214 } 214 }
215 215
216 ~scoped_ptr_impl() { 216 ~scoped_ptr_impl() {
217 if (data_.ptr != nullptr) { 217 if (data_.ptr != NULL) {
218 // Not using get_deleter() saves one function call in non-optimized 218 // Not using get_deleter() saves one function call in non-optimized
219 // builds. 219 // builds.
220 static_cast<D&>(data_)(data_.ptr); 220 static_cast<D&>(data_)(data_.ptr);
221 } 221 }
222 } 222 }
223 223
224 void reset(T* p) { 224 void reset(T* p) {
225 // This is a self-reset, which is no longer allowed: http://crbug.com/162971 225 // This is a self-reset, which is no longer allowed: http://crbug.com/162971
226 if (p != nullptr && p == data_.ptr) 226 if (p != NULL && p == data_.ptr)
227 abort(); 227 abort();
228 228
229 // Note that running data_.ptr = p can lead to undefined behavior if 229 // Note that running data_.ptr = p can lead to undefined behavior if
230 // get_deleter()(get()) deletes this. In order to prevent this, reset() 230 // get_deleter()(get()) deletes this. In order to prevent this, reset()
231 // should update the stored pointer before deleting its old value. 231 // should update the stored pointer before deleting its old value.
232 // 232 //
233 // However, changing reset() to use that behavior may cause current code to 233 // However, changing reset() to use that behavior may cause current code to
234 // break in unexpected ways. If the destruction of the owned object 234 // break in unexpected ways. If the destruction of the owned object
235 // dereferences the scoped_ptr when it is destroyed by a call to reset(), 235 // dereferences the scoped_ptr when it is destroyed by a call to reset(),
236 // then it will incorrectly dispatch calls to |p| rather than the original 236 // then it will incorrectly dispatch calls to |p| rather than the original
237 // value of |data_.ptr|. 237 // value of |data_.ptr|.
238 // 238 //
239 // During the transition period, set the stored pointer to nullptr while 239 // During the transition period, set the stored pointer to NULL while
240 // deleting the object. Eventually, this safety check will be removed to 240 // deleting the object. Eventually, this safety check will be removed to
241 // prevent the scenario initially described from occuring and 241 // prevent the scenario initially described from occuring and
242 // http://crbug.com/176091 can be closed. 242 // http://crbug.com/176091 can be closed.
243 T* old = data_.ptr; 243 T* old = data_.ptr;
244 data_.ptr = nullptr; 244 data_.ptr = NULL;
245 if (old != nullptr) 245 if (old != NULL)
246 static_cast<D&>(data_)(old); 246 static_cast<D&>(data_)(old);
247 data_.ptr = p; 247 data_.ptr = p;
248 } 248 }
249 249
250 T* get() const { return data_.ptr; } 250 T* get() const { return data_.ptr; }
251 251
252 D& get_deleter() { return data_; } 252 D& get_deleter() { return data_; }
253 const D& get_deleter() const { return data_; } 253 const D& get_deleter() const { return data_; }
254 254
255 void swap(scoped_ptr_impl& p2) { 255 void swap(scoped_ptr_impl& p2) {
256 // Standard swap idiom: 'using std::swap' ensures that std::swap is 256 // Standard swap idiom: 'using std::swap' ensures that std::swap is
257 // present in the overload set, but we call swap unqualified so that 257 // present in the overload set, but we call swap unqualified so that
258 // any more-specific overloads can be used, if available. 258 // any more-specific overloads can be used, if available.
259 using std::swap; 259 using std::swap;
260 swap(static_cast<D&>(data_), static_cast<D&>(p2.data_)); 260 swap(static_cast<D&>(data_), static_cast<D&>(p2.data_));
261 swap(data_.ptr, p2.data_.ptr); 261 swap(data_.ptr, p2.data_.ptr);
262 } 262 }
263 263
264 T* release() { 264 T* release() {
265 T* old_ptr = data_.ptr; 265 T* old_ptr = data_.ptr;
266 data_.ptr = nullptr; 266 data_.ptr = NULL;
267 return old_ptr; 267 return old_ptr;
268 } 268 }
269 269
270 private: 270 private:
271 // Needed to allow type-converting constructor. 271 // Needed to allow type-converting constructor.
272 template <typename U, typename V> friend class scoped_ptr_impl; 272 template <typename U, typename V> friend class scoped_ptr_impl;
273 273
274 // Use the empty base class optimization to allow us to have a D 274 // Use the empty base class optimization to allow us to have a D
275 // member, while avoiding any space overhead for it when D is an 275 // member, while avoiding any space overhead for it when D is an
276 // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good 276 // empty class. See e.g. http://www.cantrip.org/emptyopt.html for a good
277 // discussion of this technique. 277 // discussion of this technique.
278 struct Data : public D { 278 struct Data : public D {
279 explicit Data(T* ptr_in) : ptr(ptr_in) {} 279 explicit Data(T* ptr_in) : ptr(ptr_in) {}
280 Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {} 280 Data(T* ptr_in, const D& other) : D(other), ptr(ptr_in) {}
281 T* ptr; 281 T* ptr;
282 }; 282 };
283 283
284 Data data_; 284 Data data_;
285 285
286 DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl); 286 DISALLOW_COPY_AND_ASSIGN(scoped_ptr_impl);
287 }; 287 };
288 288
289 } // namespace internal 289 } // namespace internal
290 290
291 } // namespace base 291 } // namespace base
292 292
293 // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T> 293 // A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>
294 // automatically deletes the pointer it holds (if any). 294 // automatically deletes the pointer it holds (if any).
295 // That is, scoped_ptr<T> owns the T object that it points to. 295 // That is, scoped_ptr<T> owns the T object that it points to.
296 // Like a T*, a scoped_ptr<T> may hold either nullptr or a pointer to a T 296 // Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.
297 // object. Also like T*, scoped_ptr<T> is thread-compatible, and once you 297 // Also like T*, scoped_ptr<T> is thread-compatible, and once you
298 // dereference it, you get the thread safety guarantees of T. 298 // dereference it, you get the thread safety guarantees of T.
299 // 299 //
300 // The size of scoped_ptr is small. On most compilers, when using the 300 // The size of scoped_ptr is small. On most compilers, when using the
301 // DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will 301 // DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will
302 // increase the size proportional to whatever state they need to have. See 302 // increase the size proportional to whatever state they need to have. See
303 // comments inside scoped_ptr_impl<> for details. 303 // comments inside scoped_ptr_impl<> for details.
304 // 304 //
305 // Current implementation targets having a strict subset of C++11's 305 // Current implementation targets having a strict subset of C++11's
306 // unique_ptr<> features. Known deficiencies include not supporting move-only 306 // unique_ptr<> features. Known deficiencies include not supporting move-only
307 // deleteres, function pointers as deleters, and deleters with reference 307 // deleteres, function pointers as deleters, and deleters with reference
308 // types. 308 // types.
309 template <class T, class D = base::DefaultDeleter<T> > 309 template <class T, class D = base::DefaultDeleter<T> >
310 class scoped_ptr { 310 class scoped_ptr {
311 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) 311 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
312 312
313 COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value, 313 COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value,
314 T_is_refcounted_type_and_needs_scoped_refptr); 314 T_is_refcounted_type_and_needs_scoped_refptr);
315 315
316 public: 316 public:
317 // The element and deleter types. 317 // The element and deleter types.
318 typedef T element_type; 318 typedef T element_type;
319 typedef D deleter_type; 319 typedef D deleter_type;
320 320
321 // Constructor. Defaults to initializing with nullptr. 321 // Constructor. Defaults to initializing with NULL.
322 scoped_ptr() : impl_(nullptr) {} 322 scoped_ptr() : impl_(NULL) { }
323 323
324 // Constructor. Takes ownership of p. 324 // Constructor. Takes ownership of p.
325 explicit scoped_ptr(element_type* p) : impl_(p) {} 325 explicit scoped_ptr(element_type* p) : impl_(p) { }
326 326
327 // Constructor. Allows initialization of a stateful deleter. 327 // Constructor. Allows initialization of a stateful deleter.
328 scoped_ptr(element_type* p, const D& d) : impl_(p, d) {} 328 scoped_ptr(element_type* p, const D& d) : impl_(p, d) { }
329
330 // Constructor. Allows construction from a nullptr.
331 scoped_ptr(decltype(nullptr)) : impl_(nullptr) {}
332 329
333 // Constructor. Allows construction from a scoped_ptr rvalue for a 330 // Constructor. Allows construction from a scoped_ptr rvalue for a
334 // convertible type and deleter. 331 // convertible type and deleter.
335 // 332 //
336 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct 333 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this constructor distinct
337 // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor 334 // from the normal move constructor. By C++11 20.7.1.2.1.21, this constructor
338 // has different post-conditions if D is a reference type. Since this 335 // has different post-conditions if D is a reference type. Since this
339 // implementation does not support deleters with reference type, 336 // implementation does not support deleters with reference type,
340 // we do not need a separate move constructor allowing us to avoid one 337 // we do not need a separate move constructor allowing us to avoid one
341 // use of SFINAE. You only need to care about this if you modify the 338 // use of SFINAE. You only need to care about this if you modify the
342 // implementation of scoped_ptr. 339 // implementation of scoped_ptr.
343 template <typename U, typename V> 340 template <typename U, typename V>
344 scoped_ptr(scoped_ptr<U, V>&& other) 341 scoped_ptr(scoped_ptr<U, V> other) : impl_(&other.impl_) {
345 : impl_(&other.impl_) {
346 COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array); 342 COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array);
347 } 343 }
348 344
349 // Constructor. Move constructor for C++03 move emulation of this type. 345 // Constructor. Move constructor for C++03 move emulation of this type.
350 scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) {} 346 scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { }
351 347
352 // operator=. Allows assignment from a scoped_ptr rvalue for a convertible 348 // operator=. Allows assignment from a scoped_ptr rvalue for a convertible
353 // type and deleter. 349 // type and deleter.
354 // 350 //
355 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from 351 // IMPLEMENTATION NOTE: C++11 unique_ptr<> keeps this operator= distinct from
356 // the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated 352 // the normal move assignment operator. By C++11 20.7.1.2.3.4, this templated
357 // form has different requirements on for move-only Deleters. Since this 353 // form has different requirements on for move-only Deleters. Since this
358 // implementation does not support move-only Deleters, we do not need a 354 // implementation does not support move-only Deleters, we do not need a
359 // separate move assignment operator allowing us to avoid one use of SFINAE. 355 // separate move assignment operator allowing us to avoid one use of SFINAE.
360 // You only need to care about this if you modify the implementation of 356 // You only need to care about this if you modify the implementation of
361 // scoped_ptr. 357 // scoped_ptr.
362 template <typename U, typename V> 358 template <typename U, typename V>
363 scoped_ptr& operator=(scoped_ptr<U, V>&& rhs) { 359 scoped_ptr& operator=(scoped_ptr<U, V> rhs) {
364 COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array); 360 COMPILE_ASSERT(!base::is_array<U>::value, U_cannot_be_an_array);
365 impl_.TakeState(&rhs.impl_); 361 impl_.TakeState(&rhs.impl_);
366 return *this; 362 return *this;
367 } 363 }
368 364
369 // operator=. Allows assignment from a nullptr. Deletes the currently owned
370 // object, if any.
371 scoped_ptr& operator=(decltype(nullptr)) {
372 reset();
373 return *this;
374 }
375
376 // Reset. Deletes the currently owned object, if any. 365 // Reset. Deletes the currently owned object, if any.
377 // Then takes ownership of a new object, if given. 366 // Then takes ownership of a new object, if given.
378 void reset(element_type* p = nullptr) { impl_.reset(p); } 367 void reset(element_type* p = NULL) { impl_.reset(p); }
379 368
380 // Accessors to get the owned object. 369 // Accessors to get the owned object.
381 // operator* and operator-> will assert() if there is no current object. 370 // operator* and operator-> will assert() if there is no current object.
382 element_type& operator*() const { 371 element_type& operator*() const {
383 assert(impl_.get() != nullptr); 372 assert(impl_.get() != NULL);
384 return *impl_.get(); 373 return *impl_.get();
385 } 374 }
386 element_type* operator->() const { 375 element_type* operator->() const {
387 assert(impl_.get() != nullptr); 376 assert(impl_.get() != NULL);
388 return impl_.get(); 377 return impl_.get();
389 } 378 }
390 element_type* get() const { return impl_.get(); } 379 element_type* get() const { return impl_.get(); }
391 380
392 // Access to the deleter. 381 // Access to the deleter.
393 deleter_type& get_deleter() { return impl_.get_deleter(); } 382 deleter_type& get_deleter() { return impl_.get_deleter(); }
394 const deleter_type& get_deleter() const { return impl_.get_deleter(); } 383 const deleter_type& get_deleter() const { return impl_.get_deleter(); }
395 384
396 // Allow scoped_ptr<element_type> to be used in boolean expressions, but not 385 // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
397 // implicitly convertible to a real bool (which is dangerous). 386 // implicitly convertible to a real bool (which is dangerous).
398 // 387 //
399 // Note that this trick is only safe when the == and != operators 388 // Note that this trick is only safe when the == and != operators
400 // are declared explicitly, as otherwise "scoped_ptr1 == 389 // are declared explicitly, as otherwise "scoped_ptr1 ==
401 // scoped_ptr2" will compile but do the wrong thing (i.e., convert 390 // scoped_ptr2" will compile but do the wrong thing (i.e., convert
402 // to Testable and then do the comparison). 391 // to Testable and then do the comparison).
403 private: 392 private:
404 typedef base::internal::scoped_ptr_impl<element_type, deleter_type> 393 typedef base::internal::scoped_ptr_impl<element_type, deleter_type>
405 scoped_ptr::*Testable; 394 scoped_ptr::*Testable;
406 395
407 public: 396 public:
408 operator Testable() const { 397 operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }
409 return impl_.get() ? &scoped_ptr::impl_ : nullptr;
410 }
411 398
412 // Comparison operators. 399 // Comparison operators.
413 // These return whether two scoped_ptr refer to the same object, not just to 400 // These return whether two scoped_ptr refer to the same object, not just to
414 // two different but equal objects. 401 // two different but equal objects.
415 bool operator==(const element_type* p) const { return impl_.get() == p; } 402 bool operator==(const element_type* p) const { return impl_.get() == p; }
416 bool operator!=(const element_type* p) const { return impl_.get() != p; } 403 bool operator!=(const element_type* p) const { return impl_.get() != p; }
417 404
418 // Swap two scoped pointers. 405 // Swap two scoped pointers.
419 void swap(scoped_ptr& p2) { 406 void swap(scoped_ptr& p2) {
420 impl_.swap(p2.impl_); 407 impl_.swap(p2.impl_);
421 } 408 }
422 409
423 // Release a pointer. 410 // Release a pointer.
424 // The return value is the current pointer held by this object. If this object 411 // The return value is the current pointer held by this object.
425 // holds a nullptr, the return value is nullptr. After this operation, this 412 // If this object holds a NULL pointer, the return value is NULL.
426 // object will hold a nullptr, and will not own the object any more. 413 // After this operation, this object will hold a NULL pointer,
414 // and will not own the object any more.
427 element_type* release() WARN_UNUSED_RESULT { 415 element_type* release() WARN_UNUSED_RESULT {
428 return impl_.release(); 416 return impl_.release();
429 } 417 }
430 418
431 // C++98 doesn't support functions templates with default parameters which 419 // C++98 doesn't support functions templates with default parameters which
432 // makes it hard to write a PassAs() that understands converting the deleter 420 // makes it hard to write a PassAs() that understands converting the deleter
433 // while preserving simple calling semantics. 421 // while preserving simple calling semantics.
434 // 422 //
435 // Until there is a use case for PassAs() with custom deleters, just ignore 423 // Until there is a use case for PassAs() with custom deleters, just ignore
436 // the custom deleter. 424 // the custom deleter.
(...skipping 20 matching lines...) Expand all
457 445
458 template <class T, class D> 446 template <class T, class D>
459 class scoped_ptr<T[], D> { 447 class scoped_ptr<T[], D> {
460 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue) 448 MOVE_ONLY_TYPE_FOR_CPP_03(scoped_ptr, RValue)
461 449
462 public: 450 public:
463 // The element and deleter types. 451 // The element and deleter types.
464 typedef T element_type; 452 typedef T element_type;
465 typedef D deleter_type; 453 typedef D deleter_type;
466 454
467 // Constructor. Defaults to initializing with nullptr. 455 // Constructor. Defaults to initializing with NULL.
468 scoped_ptr() : impl_(nullptr) {} 456 scoped_ptr() : impl_(NULL) { }
469 457
470 // Constructor. Stores the given array. Note that the argument's type 458 // Constructor. Stores the given array. Note that the argument's type
471 // must exactly match T*. In particular: 459 // must exactly match T*. In particular:
472 // - it cannot be a pointer to a type derived from T, because it is 460 // - it cannot be a pointer to a type derived from T, because it is
473 // inherently unsafe in the general case to access an array through a 461 // inherently unsafe in the general case to access an array through a
474 // pointer whose dynamic type does not match its static type (eg., if 462 // pointer whose dynamic type does not match its static type (eg., if
475 // T and the derived types had different sizes access would be 463 // T and the derived types had different sizes access would be
476 // incorrectly calculated). Deletion is also always undefined 464 // incorrectly calculated). Deletion is also always undefined
477 // (C++98 [expr.delete]p3). If you're doing this, fix your code. 465 // (C++98 [expr.delete]p3). If you're doing this, fix your code.
466 // - it cannot be NULL, because NULL is an integral expression, not a
467 // pointer to T. Use the no-argument version instead of explicitly
468 // passing NULL.
478 // - it cannot be const-qualified differently from T per unique_ptr spec 469 // - it cannot be const-qualified differently from T per unique_ptr spec
479 // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting 470 // (http://cplusplus.github.com/LWG/lwg-active.html#2118). Users wanting
480 // to work around this may use implicit_cast<const T*>(). 471 // to work around this may use implicit_cast<const T*>().
481 // However, because of the first bullet in this comment, users MUST 472 // However, because of the first bullet in this comment, users MUST
482 // NOT use implicit_cast<Base*>() to upcast the static type of the array. 473 // NOT use implicit_cast<Base*>() to upcast the static type of the array.
483 explicit scoped_ptr(element_type* array) : impl_(array) {} 474 explicit scoped_ptr(element_type* array) : impl_(array) { }
484
485 // Constructor. Allows construction from a nullptr.
486 scoped_ptr(decltype(nullptr)) : impl_(nullptr) {}
487
488 // Constructor. Allows construction from a scoped_ptr rvalue.
489 scoped_ptr(scoped_ptr&& other) : impl_(&other.impl_) {}
490 475
491 // Constructor. Move constructor for C++03 move emulation of this type. 476 // Constructor. Move constructor for C++03 move emulation of this type.
492 scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) {} 477 scoped_ptr(RValue rvalue) : impl_(&rvalue.object->impl_) { }
493
494 // operator=. Allows assignment from a scoped_ptr rvalue.
495 scoped_ptr& operator=(scoped_ptr&& rhs) {
496 impl_.TakeState(&rhs.impl_);
497 return *this;
498 }
499 478
500 // operator=. Move operator= for C++03 move emulation of this type. 479 // operator=. Move operator= for C++03 move emulation of this type.
501 scoped_ptr& operator=(RValue rhs) { 480 scoped_ptr& operator=(RValue rhs) {
502 impl_.TakeState(&rhs.object->impl_); 481 impl_.TakeState(&rhs.object->impl_);
503 return *this; 482 return *this;
504 } 483 }
505 484
506 // operator=. Allows assignment from a nullptr. Deletes the currently owned
507 // array, if any.
508 scoped_ptr& operator=(decltype(nullptr)) {
509 reset();
510 return *this;
511 }
512
513 // Reset. Deletes the currently owned array, if any. 485 // Reset. Deletes the currently owned array, if any.
514 // Then takes ownership of a new object, if given. 486 // Then takes ownership of a new object, if given.
515 void reset(element_type* array = nullptr) { impl_.reset(array); } 487 void reset(element_type* array = NULL) { impl_.reset(array); }
516 488
517 // Accessors to get the owned array. 489 // Accessors to get the owned array.
518 element_type& operator[](size_t i) const { 490 element_type& operator[](size_t i) const {
519 assert(impl_.get() != nullptr); 491 assert(impl_.get() != NULL);
520 return impl_.get()[i]; 492 return impl_.get()[i];
521 } 493 }
522 element_type* get() const { return impl_.get(); } 494 element_type* get() const { return impl_.get(); }
523 495
524 // Access to the deleter. 496 // Access to the deleter.
525 deleter_type& get_deleter() { return impl_.get_deleter(); } 497 deleter_type& get_deleter() { return impl_.get_deleter(); }
526 const deleter_type& get_deleter() const { return impl_.get_deleter(); } 498 const deleter_type& get_deleter() const { return impl_.get_deleter(); }
527 499
528 // Allow scoped_ptr<element_type> to be used in boolean expressions, but not 500 // Allow scoped_ptr<element_type> to be used in boolean expressions, but not
529 // implicitly convertible to a real bool (which is dangerous). 501 // implicitly convertible to a real bool (which is dangerous).
530 private: 502 private:
531 typedef base::internal::scoped_ptr_impl<element_type, deleter_type> 503 typedef base::internal::scoped_ptr_impl<element_type, deleter_type>
532 scoped_ptr::*Testable; 504 scoped_ptr::*Testable;
533 505
534 public: 506 public:
535 operator Testable() const { 507 operator Testable() const { return impl_.get() ? &scoped_ptr::impl_ : NULL; }
536 return impl_.get() ? &scoped_ptr::impl_ : nullptr;
537 }
538 508
539 // Comparison operators. 509 // Comparison operators.
540 // These return whether two scoped_ptr refer to the same object, not just to 510 // These return whether two scoped_ptr refer to the same object, not just to
541 // two different but equal objects. 511 // two different but equal objects.
542 bool operator==(element_type* array) const { return impl_.get() == array; } 512 bool operator==(element_type* array) const { return impl_.get() == array; }
543 bool operator!=(element_type* array) const { return impl_.get() != array; } 513 bool operator!=(element_type* array) const { return impl_.get() != array; }
544 514
545 // Swap two scoped pointers. 515 // Swap two scoped pointers.
546 void swap(scoped_ptr& p2) { 516 void swap(scoped_ptr& p2) {
547 impl_.swap(p2.impl_); 517 impl_.swap(p2.impl_);
548 } 518 }
549 519
550 // Release a pointer. 520 // Release a pointer.
551 // The return value is the current pointer held by this object. If this object 521 // The return value is the current pointer held by this object.
552 // holds a nullptr, the return value is nullptr. After this operation, this 522 // If this object holds a NULL pointer, the return value is NULL.
553 // object will hold a nullptr, and will not own the object any more. 523 // After this operation, this object will hold a NULL pointer,
524 // and will not own the object any more.
554 element_type* release() WARN_UNUSED_RESULT { 525 element_type* release() WARN_UNUSED_RESULT {
555 return impl_.release(); 526 return impl_.release();
556 } 527 }
557 528
558 private: 529 private:
559 // Force element_type to be a complete type. 530 // Force element_type to be a complete type.
560 enum { type_must_be_complete = sizeof(element_type) }; 531 enum { type_must_be_complete = sizeof(element_type) };
561 532
562 // Actually hold the data. 533 // Actually hold the data.
563 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_; 534 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
601 572
602 // A function to convert T* into scoped_ptr<T> 573 // A function to convert T* into scoped_ptr<T>
603 // Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation 574 // Doing e.g. make_scoped_ptr(new FooBarBaz<type>(arg)) is a shorter notation
604 // for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg)) 575 // for scoped_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg))
605 template <typename T> 576 template <typename T>
606 scoped_ptr<T> make_scoped_ptr(T* ptr) { 577 scoped_ptr<T> make_scoped_ptr(T* ptr) {
607 return scoped_ptr<T>(ptr); 578 return scoped_ptr<T>(ptr);
608 } 579 }
609 580
610 #endif // BASE_MEMORY_SCOPED_PTR_H_ 581 #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