Consider a standard class implementation that makes use of PImpl, but uses a std::unique_ptr
to manage the implementation object's lifetime:
class MyClass {
public:
class Impl;
MyClass();
~MyClass(); // Note: No default here
void someFunction();
private:
std::unique_ptr< Impl > m_impl;
};
Since we are not defaulting any of the standard functions (at least I think having a non-default constructor prevents the compiler from generating other defaults like move-assignment operator), we should have no problem using the incomplete MyClass::Impl
type as type argument for unique_ptr
.
Now, the goal of PImpl (afaik) is to use C++ in an ABI compatible way. However, to my knowledge there is no actual guarantee that implementations of std::unique_ptr
has the exact same size (in bytes). Therefore, it seems possible (at least in theory) that I compile my library against one STL implementation and then try to use it in code that uses a different STL implementation, that implements std::unique_ptr
to have a different size. Wouldn't this break ABI compatibility as now the object that is instantiated across API boundaries is assumed to have different sizes depending on which side of the boundary you are on?
Thus: Does sticking to the PImpl idiom actually guarantee ABI compatibility (in contexts in which a corresponding C library would provide it - aka: same hardware, OS, etc.)?
Related: