Index: base/memory/scoped_ptr.h |
diff --git a/base/memory/scoped_ptr.h b/base/memory/scoped_ptr.h |
index c4d75a4b0583d1c75404c1b4b16ec1d369a89bb4..a7ff92235235383051010a94a51622a49fba6fc7 100644 |
--- a/base/memory/scoped_ptr.h |
+++ b/base/memory/scoped_ptr.h |
@@ -86,6 +86,8 @@ |
#include <algorithm> // For std::swap(). |
#include <iosfwd> |
+#include <memory> |
+#include <utility> |
#include "base/basictypes.h" |
#include "base/compiler_specific.h" |
@@ -99,61 +101,6 @@ class RefCountedBase; |
class RefCountedThreadSafeBase; |
} // namespace subtle |
-// Function object which deletes its parameter, which must be a pointer. |
-// If C is an array type, invokes 'delete[]' on the parameter; otherwise, |
-// invokes 'delete'. The default deleter for scoped_ptr<T>. |
-template <class T> |
-struct DefaultDeleter { |
dcheng
2015/11/11 16:18:34
I tried using a type alias, but apparently the sta
|
- DefaultDeleter() {} |
- template <typename U> DefaultDeleter(const DefaultDeleter<U>& other) { |
- // IMPLEMENTATION NOTE: C++11 20.7.1.1.2p2 only provides this constructor |
- // if U* is implicitly convertible to T* and U is not an array type. |
- // |
- // Correct implementation should use SFINAE to disable this |
- // constructor. However, since there are no other 1-argument constructors, |
- // using a COMPILE_ASSERT() based on is_convertible<> and requiring |
- // complete types is simpler and will cause compile failures for equivalent |
- // misuses. |
- // |
- // Note, the is_convertible<U*, T*> check also ensures that U is not an |
- // array. T is guaranteed to be a non-array, so any U* where U is an array |
- // cannot convert to T*. |
- enum { T_must_be_complete = sizeof(T) }; |
- enum { U_must_be_complete = sizeof(U) }; |
- COMPILE_ASSERT((base::is_convertible<U*, T*>::value), |
- U_ptr_must_implicitly_convert_to_T_ptr); |
- } |
- inline void operator()(T* ptr) const { |
- enum { type_must_be_complete = sizeof(T) }; |
- delete ptr; |
- } |
-}; |
- |
-// Specialization of DefaultDeleter for array types. |
-template <class T> |
-struct DefaultDeleter<T[]> { |
- inline void operator()(T* ptr) const { |
- enum { type_must_be_complete = sizeof(T) }; |
- delete[] ptr; |
- } |
- |
- private: |
- // Disable this operator for any U != T because it is undefined to execute |
- // an array delete when the static type of the array mismatches the dynamic |
- // type. |
- // |
- // References: |
- // C++98 [expr.delete]p3 |
- // http://cplusplus.github.com/LWG/lwg-defects.html#938 |
- template <typename U> void operator()(U* array) const; |
-}; |
- |
-template <class T, int n> |
-struct DefaultDeleter<T[n]> { |
- // Never allow someone to declare something like scoped_ptr<int[10]>. |
- COMPILE_ASSERT(sizeof(T) == -1, do_not_use_array_with_size_as_type); |
-}; |
- |
// Function object which invokes 'free' on its parameter, which must be |
// a pointer. Can be used to store malloc-allocated pointers in scoped_ptr: |
// |
@@ -208,6 +155,12 @@ class scoped_ptr_impl { |
} |
template <typename U, typename V> |
+ void TakeState(std::unique_ptr<U, V>* other) { |
+ reset(other->release()); |
+ get_deleter() = other->get_deleter(); |
+ } |
+ |
+ template <typename U, typename V> |
void TakeState(scoped_ptr_impl<U, V>* other) { |
// See comment in templated constructor above regarding lack of support |
// for move-only deleters. |
@@ -303,7 +256,7 @@ class scoped_ptr_impl { |
// unique_ptr<> features. Known deficiencies include not supporting move-only |
// deleteres, function pointers as deleters, and deleters with reference |
// types. |
-template <class T, class D = base::DefaultDeleter<T> > |
+template <class T, class D = std::default_delete<T>> |
class scoped_ptr { |
MOVE_ONLY_TYPE_WITH_MOVE_CONSTRUCTOR_FOR_CPP_03(scoped_ptr) |
@@ -422,6 +375,22 @@ class scoped_ptr { |
return impl_.release(); |
} |
+ // Conversion shims to help with the std::unique_ptr transition. |
+ template <typename U, typename V> |
+ scoped_ptr(std::unique_ptr<U, V>&& p) |
+ : impl_(p.release(), p.get_deleter()) {} |
+ |
+ template <typename U, typename V> |
+ scoped_ptr& operator=(std::unique_ptr<U, V>&& p) { |
+ impl_.TakeState(&p); |
+ return *this; |
+ } |
+ |
+ template <typename U, typename V> |
+ 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
|
+ return std::unique_ptr<U, V>(release(), get_deleter()); |
+ } |
+ |
private: |
// Needed to reach into |impl_| in the constructor. |
template <typename U, typename V> friend class scoped_ptr; |
@@ -527,6 +496,19 @@ class scoped_ptr<T[], D> { |
return impl_.release(); |
} |
+ // Conversion shims to help with the std::unique_ptr transition. |
+ 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?
|
+ : impl_(p.release(), p.get_deleter()) {} |
+ |
+ scoped_ptr& operator=(std::unique_ptr<T[], D>&& p) { |
+ impl_.TakeState(&p); |
+ return *this; |
+ } |
+ |
+ 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.
|
+ return std::unique_ptr<T[], D>(release(), get_deleter()); |
+ } |
+ |
private: |
// Force element_type to be a complete type. |
enum { type_must_be_complete = sizeof(element_type) }; |