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?
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_;