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

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

Issue 1432193002: Add std::unique_ptr conversions to scoped_ptr. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: I wish my local build wasn't randomly broken Created 5 years, 1 month 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') | ipc/ipc_channel_proxy.cc » ('J')
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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 79
80 // This is an implementation designed to match the anticipated future TR2 80 // This is an implementation designed to match the anticipated future TR2
81 // implementation of the scoped_ptr class. 81 // implementation of the scoped_ptr class.
82 82
83 #include <assert.h> 83 #include <assert.h>
84 #include <stddef.h> 84 #include <stddef.h>
85 #include <stdlib.h> 85 #include <stdlib.h>
86 86
87 #include <algorithm> // For std::swap(). 87 #include <algorithm> // For std::swap().
88 #include <iosfwd> 88 #include <iosfwd>
89 #include <memory>
90 #include <utility>
89 91
90 #include "base/basictypes.h" 92 #include "base/basictypes.h"
91 #include "base/compiler_specific.h" 93 #include "base/compiler_specific.h"
92 #include "base/move.h" 94 #include "base/move.h"
93 #include "base/template_util.h" 95 #include "base/template_util.h"
94 96
95 namespace base { 97 namespace base {
96 98
97 namespace subtle { 99 namespace subtle {
98 class RefCountedBase; 100 class RefCountedBase;
99 class RefCountedThreadSafeBase; 101 class RefCountedThreadSafeBase;
100 } // namespace subtle 102 } // namespace subtle
101 103
102 // Function object which deletes its parameter, which must be a pointer.
103 // If C is an array type, invokes 'delete[]' on the parameter; otherwise,
104 // invokes 'delete'. The default deleter for scoped_ptr<T>.
105 template <class T>
106 struct DefaultDeleter {
dcheng 2015/11/11 16:18:34 I tried using a type alias, but apparently the sta
107 DefaultDeleter() {}
108 template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) {
109 // IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor
110 // if U* is implicitly convertible to T* and U is not an array type.
111 //
112 // Correct implementation should use SFINAE to disable this
113 // constructor. However, since there are no other 1-argument constructors,
114 // using a COMPILE_ASSERT() based on is_convertible<> and requiring
115 // complete types is simpler and will cause compile failures for equivalent
116 // misuses.
117 //
118 // Note, the is_convertible<U*, T*> check also ensures that U is not an
119 // array. T is guaranteed to be a non-array, so any U* where U is an array
120 // cannot convert to T*.
121 enum { T_must_be_complete = sizeof(T) };
122 enum { U_must_be_complete = sizeof(U) };
123 COMPILE_ASSERT((base::is_convertible<U*, T*>::value),
124 U_ptr_must_implicitly_convert_to_T_ptr);
125 }
126 inline void operator()(T* ptr) const {
127 enum { type_must_be_complete = sizeof(T) };
128 delete ptr;
129 }
130 };
131
132 // Specialization of DefaultDeleter for array types.
133 template <class T>
134 struct DefaultDeleter<T[]> {
135 inline void operator()(T* ptr) const {
136 enum { type_must_be_complete = sizeof(T) };
137 delete[] ptr;
138 }
139
140 private:
141 // Disable this operator for any U != T because it is undefined to execute
142 // an array delete when the static type of the array mismatches the dynamic
143 // type.
144 //
145 // References:
146 // C++98 [expr.delete]p3
147 // http://cplusplus.github.com/LWG/lwg-defects.html#938
148 template <typename U> void operator()(U* array) const;
149 };
150
151 template <class T, int n>
152 struct DefaultDeleter<T[n]> {
153 // Never allow someone to declare something like scoped_ptr<int[10]>.
154 COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type);
155 };
156
157 // Function object which invokes 'free' on its parameter, which must be 104 // Function object which invokes 'free' on its parameter, which must be
158 // a pointer. Can be used to store malloc-allocated pointers in scoped_ptr: 105 // a pointer. Can be used to store malloc-allocated pointers in scoped_ptr:
159 // 106 //
160 // scoped_ptr<int, base::FreeDeleter> foo_ptr( 107 // scoped_ptr<int, base::FreeDeleter> foo_ptr(
161 // static_cast<int*>(malloc(sizeof(int)))); 108 // static_cast<int*>(malloc(sizeof(int))));
162 struct FreeDeleter { 109 struct FreeDeleter {
163 inline void operator()(void* ptr) const { 110 inline void operator()(void* ptr) const {
164 free(ptr); 111 free(ptr);
165 } 112 }
166 }; 113 };
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 template <typename U, typename V> 148 template <typename U, typename V>
202 scoped_ptr_impl(scoped_ptr_impl<U, V>* other) 149 scoped_ptr_impl(scoped_ptr_impl<U, V>* other)
203 : data_(other->release(), other->get_deleter()) { 150 : data_(other->release(), other->get_deleter()) {
204 // We do not support move-only deleters. We could modify our move 151 // We do not support move-only deleters. We could modify our move
205 // emulation to have base::subtle::move() and base::subtle::forward() 152 // emulation to have base::subtle::move() and base::subtle::forward()
206 // functions that are imperfect emulations of their C++11 equivalents, 153 // functions that are imperfect emulations of their C++11 equivalents,
207 // but until there's a requirement, just assume deleters are copyable. 154 // but until there's a requirement, just assume deleters are copyable.
208 } 155 }
209 156
210 template <typename U, typename V> 157 template <typename U, typename V>
158 void TakeState(std::unique_ptr<U, V>* other) {
159 reset(other->release());
160 get_deleter() = other->get_deleter();
161 }
162
163 template <typename U, typename V>
211 void TakeState(scoped_ptr_impl<U, V>* other) { 164 void TakeState(scoped_ptr_impl<U, V>* other) {
212 // See comment in templated constructor above regarding lack of support 165 // See comment in templated constructor above regarding lack of support
213 // for move-only deleters. 166 // for move-only deleters.
214 reset(other->release()); 167 reset(other->release());
215 get_deleter() = other->get_deleter(); 168 get_deleter() = other->get_deleter();
216 } 169 }
217 170
218 ~scoped_ptr_impl() { 171 ~scoped_ptr_impl() {
219 // Match libc++, which calls reset() in its destructor. 172 // Match libc++, which calls reset() in its destructor.
220 // Use nullptr as the new value for three reasons: 173 // Use nullptr as the new value for three reasons:
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
296 // 249 //
297 // The size of scoped_ptr is small. On most compilers, when using the 250 // The size of scoped_ptr is small. On most compilers, when using the
298 // DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will 251 // DefaultDeleter, sizeof(scoped_ptr<T>) == sizeof(T*). Custom deleters will
299 // increase the size proportional to whatever state they need to have. See 252 // increase the size proportional to whatever state they need to have. See
300 // comments inside scoped_ptr_impl<> for details. 253 // comments inside scoped_ptr_impl<> for details.
301 // 254 //
302 // Current implementation targets having a strict subset of C++11's 255 // Current implementation targets having a strict subset of C++11's
303 // unique_ptr<> features. Known deficiencies include not supporting move-only 256 // unique_ptr<> features. Known deficiencies include not supporting move-only
304 // deleteres, function pointers as deleters, and deleters with reference 257 // deleteres, function pointers as deleters, and deleters with reference
305 // types. 258 // types.
306 template <class T, class D = base::DefaultDeleter<T> > 259 template <class T, class D = std::default_delete<T>>
307 class scoped_ptr { 260 class scoped_ptr {
308 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) 261 MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr)
309 262
310 COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value, 263 COMPILE_ASSERT(base::internal::IsNotRefCounted<T>::value,
311 T_is_refcounted_type_and_needs_scoped_refptr); 264 T_is_refcounted_type_and_needs_scoped_refptr);
312 265
313 public: 266 public:
314 // The element and deleter types. 267 // The element and deleter types.
315 typedef T element_type; 268 typedef T element_type;
316 typedef D deleter_type; 269 typedef D deleter_type;
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 } 368 }
416 369
417 // Release a pointer. 370 // Release a pointer.
418 // The return value is the current pointer held by this object. If this object 371 // The return value is the current pointer held by this object. If this object
419 // holds a nullptr, the return value is nullptr. After this operation, this 372 // holds a nullptr, the return value is nullptr. After this operation, this
420 // object will hold a nullptr, and will not own the object any more. 373 // object will hold a nullptr, and will not own the object any more.
421 element_type* release() WARN_UNUSED_RESULT { 374 element_type* release() WARN_UNUSED_RESULT {
422 return impl_.release(); 375 return impl_.release();
423 } 376 }
424 377
378 // Conversion shims to help with the std::unique_ptr transition.
379 template <typename U, typename V>
380 scoped_ptr(std::unique_ptr<U, V>&& p)
381 : impl_(p.release(), p.get_deleter()) {}
382
383 template <typename U, typename V>
384 scoped_ptr& operator=(std::unique_ptr<U, V>&& p) {
385 impl_.TakeState(&p);
386 return *this;
387 }
388
389 template <typename U, typename V>
390 operator std::unique_ptr<U, V>() && {
danakj 2015/11/14 01:29:31 Vlad pointed out that this doesn't work yet in MSV
dcheng 2015/11/14 01:37:10 Argh. That's obnoxious. Having asymmetrical ways t
391 return std::unique_ptr<U, V>(release(), get_deleter());
392 }
393
425 private: 394 private:
426 // Needed to reach into |impl_| in the constructor. 395 // Needed to reach into |impl_| in the constructor.
427 template <typename U, typename V> friend class scoped_ptr; 396 template <typename U, typename V> friend class scoped_ptr;
428 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_; 397 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
429 398
430 // Forbidden for API compatibility with std::unique_ptr. 399 // Forbidden for API compatibility with std::unique_ptr.
431 explicit scoped_ptr(int disallow_construction_from_null); 400 explicit scoped_ptr(int disallow_construction_from_null);
432 401
433 // Forbid comparison of scoped_ptr types. If U != T, it totally 402 // Forbid comparison of scoped_ptr types. If U != T, it totally
434 // doesn't make sense, and if U == T, it still doesn't make sense 403 // doesn't make sense, and if U == T, it still doesn't make sense
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 } 489 }
521 490
522 // Release a pointer. 491 // Release a pointer.
523 // The return value is the current pointer held by this object. If this object 492 // The return value is the current pointer held by this object. If this object
524 // holds a nullptr, the return value is nullptr. After this operation, this 493 // holds a nullptr, the return value is nullptr. After this operation, this
525 // object will hold a nullptr, and will not own the object any more. 494 // object will hold a nullptr, and will not own the object any more.
526 element_type* release() WARN_UNUSED_RESULT { 495 element_type* release() WARN_UNUSED_RESULT {
527 return impl_.release(); 496 return impl_.release();
528 } 497 }
529 498
499 // Conversion shims to help with the std::unique_ptr transition.
500 scoped_ptr(std::unique_ptr<T[], D>&& p)
dcheng 2015/11/11 16:18:34 To keep things simple, the T[] specializations jus
danakj 2015/11/14 01:29:31 Can you put that in the comment?
501 : impl_(p.release(), p.get_deleter()) {}
502
503 scoped_ptr& operator=(std::unique_ptr<T[], D>&& p) {
504 impl_.TakeState(&p);
505 return *this;
506 }
507
508 operator std::unique_ptr<T[], D>() && {
danakj 2015/11/14 01:29:31 explain the && here too
danakj 2015/11/14 01:30:06 oops, nevermind this one.
509 return std::unique_ptr<T[], D>(release(), get_deleter());
510 }
511
530 private: 512 private:
531 // Force element_type to be a complete type. 513 // Force element_type to be a complete type.
532 enum { type_must_be_complete = sizeof(element_type) }; 514 enum { type_must_be_complete = sizeof(element_type) };
533 515
534 // Actually hold the data. 516 // Actually hold the data.
535 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_; 517 base::internal::scoped_ptr_impl<element_type, deleter_type> impl_;
536 518
537 // Disable initialization from any type other than element_type*, by 519 // Disable initialization from any type other than element_type*, by
538 // providing a constructor that matches such an initialization, but is 520 // providing a constructor that matches such an initialization, but is
539 // private and has no definition. This is disabled because it is not safe to 521 // private and has no definition. This is disabled because it is not safe to
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
578 scoped_ptr<T> make_scoped_ptr(T* ptr) { 560 scoped_ptr<T> make_scoped_ptr(T* ptr) {
579 return scoped_ptr<T>(ptr); 561 return scoped_ptr<T>(ptr);
580 } 562 }
581 563
582 template <typename T> 564 template <typename T>
583 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) { 565 std::ostream& operator<<(std::ostream& out, const scoped_ptr<T>& p) {
584 return out << p.get(); 566 return out << p.get();
585 } 567 }
586 568
587 #endif // BASE_MEMORY_SCOPED_PTR_H_ 569 #endif // BASE_MEMORY_SCOPED_PTR_H_
OLDNEW
« no previous file with comments | « no previous file | base/memory/scoped_ptr_unittest.cc » ('j') | ipc/ipc_channel_proxy.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698