How does the custom deleter of std::unique_ptr work?

后端 未结 4 501
青春惊慌失措
青春惊慌失措 2020-11-27 11:47

According to N3290, std::unique_ptr accepts a deleter argument in its constructor.

However, I can\'t get that to work with Visual C++ 10.0 or MinGW g++

4条回答
  •  囚心锁ツ
    2020-11-27 12:31

    My question has been pretty well answered already.

    But just in case people wondered, I had the mistaken belief that a unique_ptr could be moved to a unique_ptr and would then remember the deleter for the Derived object, i.e., that Base would not need to have a virtual destructor. That was wrong. I'd select Kerrek SB's comment as "the answer", except one cannot do that for a comment.

    @Howard: the code below illustrates one way to achieve what I believed the cost of a dynamically assigned deleter had to mean that unique_ptr supported out of the box:

    #include 
    #include            // std::unique_ptr
    #include        // function
    #include           // move
    #include 
    using namespace std;
    
    class Base
    {
    public:
        Base() { cout << "Base:" << endl; }
        ~Base() { cout << "Base::" << endl; }
        virtual string message() const { return "Message from Base!"; }
    };
    
    class Derived
        : public Base
    {
    public:
        Derived() { cout << "Derived::" << endl; }
        ~Derived() { cout << "Derived::" << endl; }
        virtual string message() const { return "Message from Derived!"; }
    };
    
    class BoundDeleter
    {
    private:
        typedef void (*DeleteFunc)( void* p );
    
        DeleteFunc  deleteFunc_;
        void*       pObject_;
    
        template< class Type >
        static void deleteFuncImpl( void* p )
        {
            delete static_cast< Type* >( p );
        }
    
    public:
        template< class Type >
        BoundDeleter( Type* pObject )
            : deleteFunc_( &deleteFuncImpl< Type > )
            , pObject_( pObject )
        {}
    
        BoundDeleter( BoundDeleter&& other )
            : deleteFunc_( move( other.deleteFunc_ ) )
            , pObject_( move( other.pObject_ ) )
        {}
    
        void operator() (void*) const
        {
            deleteFunc_( pObject_ );
        }
    };
    
    template< class Type >
    class SafeCleanupUniquePtr
        : protected unique_ptr< Type, BoundDeleter >
    {
    public:
        typedef unique_ptr< Type, BoundDeleter >    Base;
    
        using Base::operator->;
        using Base::operator*;
    
        template< class ActualType >
        SafeCleanupUniquePtr( ActualType* p )
            : Base( p, BoundDeleter( p ) )
        {}
    
        template< class Other >
        SafeCleanupUniquePtr( SafeCleanupUniquePtr< Other >&& other )
            : Base( move( other ) )
        {}
    };
    
    int main()
    {
        SafeCleanupUniquePtr< Base >  p( new Derived );
        cout << p->message() << endl;
    }
    

提交回复
热议问题