Search code examples
c++c++11shared-ptrunique-ptr

incomplete types with shared_ptr and unique_ptr


I would like to understand why unique_ptr destructors require the type to be complete upon destruction while that isn't the case with shared_ptr. This blog from Howard Hinnant briefly mentions it has to do with static vs. dynamic deleters. I'm looking for a more detailed explanation of why that might be the case (it may be compiler implementation specific in which case an example would be helpful). With dynamic deleters, does it restrict the destructor from being inlined?


Solution

  • Howard Hinnant was simplifying. What he precisely meant was if you use the default deleter for std::unique_ptr, you need a complete type. For the default deleter, it simply calls delete for you.

    The gist of static and dynamic deleters is

    class A;
    
    void static_delete(A* p)
    {
        delete p;
    }
    
    void (*dynamic_delete)(A*) = /* somehow */;
    
    int main()
    {
        A* p = /* somehow */;
        static_delete(p);  // undefined behaviour
        dynamic_delete(p); // maybe not
    }
    

    As long asdynamic_delete points to a function that's defined where A is also defined, you have well-defined behaviour.

    To prevent undefined behaviour, the default deleter checks for a complete type, which may be implemented as

    void default_delete(A* p)
    {
        static_assert(sizeof(A) > 0);
        delete p;
    }