std::unique_ptr and Incomplete Types: A Deeper Look
Consider the pimpl idiom employing 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, a compile error arises due to an incomplete type:
"Invalid application of 'sizeof' to an incomplete type 'uixx::window::window_impl'"
Traditionally, std::unique_ptr is compatible with incomplete types. So, where lies the issue?
The Crux of the Matter: Destruction
The key resides in destruction. If pimpl is used with unique_ptr, the destructor must be declared explicitly:
class foo { class impl; std::unique_ptr<impl> impl_; public: foo(); // Constructor may need external definition ~foo(); // Implement (braceless or with = default;) once impl is complete };
If not, the compiler generates a default destructor requiring a complete declaration of foo::impl.
Template Problems and Static Duration Instances
With template constructors, complications arise even if the impl_ member is not constructed:
template <typename T> foo::foo(T bar) { // Compiler requires knowledge of impl_ destruction at compile time! }
Additionally, using unique_ptr with incomplete types at namespace scope fails:
class impl; std::unique_ptr<impl> impl_;
The compiler needs to know how to destroy this static duration object. A workaround involves defining a custom type:
class impl; struct ptr_impl : std::unique_ptr<impl> { ~ptr_impl(); // Implement (empty body) elsewhere } impl_;
The above is the detailed content of Why Does `std::unique_ptr` Fail with Incomplete Types in Pimpl Idiom?. For more information, please follow other related articles on the PHP Chinese website!