Chromium Code Reviews| 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) }; |