c++unique-ptrincomplete-typelibc++

std::unique_ptr with an incomplete type won't compile


I'm using the pimpl-idiom with std::unique_ptr:

class window {
  window(const rectangle& rect);

private:
  class window_impl; // defined elsewhere
  std::unique_ptr<window_impl> impl_; // won't compile
};

However, I get a compile error regarding the use of an incomplete type, on line 304 in <memory>:

Invalid application of 'sizeof' to an incomplete type 'uixx::window::window_impl'

For as far as I know, std::unique_ptr should be able to be used with an incomplete type. Is this a bug in libc++ or am I doing something wrong here?


Solution

  • Here are some examples of std::unique_ptr with incomplete types. The problem lies in destruction.

    If you use pimpl with unique_ptr, you need to declare a destructor:

    class foo
    { 
        class impl;
        std::unique_ptr<impl> impl_;
    
    public:
        foo(); // You may need a def. constructor to be defined elsewhere
    
        ~foo(); // Implement (with {}, or with = default;) where impl is complete
    };
    

    because otherwise the compiler generates a default one, and it needs a complete declaration of foo::impl for this.

    If you have template constructors, then you're screwed, even if you don't construct the impl_ member:

    template <typename T>
    foo::foo(T bar) 
    {
        // Here the compiler needs to know how to
        // destroy impl_ in case an exception is
        // thrown !
    }
    

    At namespace scope, using unique_ptr will not work either:

    class impl;
    std::unique_ptr<impl> impl_;
    

    since the compiler must know here how to destroy this static duration object. A workaround is:

    class impl;
    struct ptr_impl : std::unique_ptr<impl>
    {
        ~ptr_impl(); // Implement (empty body) elsewhere
    } impl_;