2

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:

Raven
  • 2,951
  • 2
  • 26
  • 42
  • 3
    If you have 2 different Standard Libraries in one program it's broken. At a minimum Undefined Behaviour as the program will be breaking the [One Definition Rule](https://en.cppreference.com/w/cpp/language/definition#One_Definition_Rule). – Richard Critten Mar 14 '23 at 18:11
  • On any sane implementation `unique_ptr` (with default deleter) won't have anything other than a pointer in it, isn't it? If you're worried about that, you could make your own `unique_ptr`, but that's a bit silly. – HolyBlackCat Mar 14 '23 at 18:16
  • 1
    @RichardCritten isn't ODR about definitions within a given translation unit? if so, I'm not sure it would actually be violated, if you compile your program with one STL but link to a library built against a different STL. Those definitions shouldn't ever cross during compilation as the compilations are completely separate... – Raven Mar 14 '23 at 18:17
  • @HolyBlackCat, I agree. I just wanted to know if the standards makes any guarantees in that regard or if this is one of the (many) places where one just relies on "about everyone does it like this anyway" – Raven Mar 14 '23 at 18:18
  • 1
    @Raven In the standard's universe, there's only one standard library. – HolyBlackCat Mar 14 '23 at 18:19
  • The c++ standard does not cover any ABI constraints - it is worded in terms of the c++ [abstract state machine](https://eel.is/c++draft/intro#abstract-1), implementations are free to choose however they want to translate that to actual bytecode for the specific target you're building for. So you'll have to check what your compiler promises in terms of abi compatibility. (Example: [gcc ABI Policy](https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html)) – Turtlefight Mar 14 '23 at 18:26
  • Note that even with the same compiler version and the same standard library you can still get ABI-incompatible code; e.g. if your code is compiled with `-fno-exceptions`, but links against another library that is not build with that flag -> ABI incompatible with gcc. Upgrading your compiler can also break your ABI compatibility (even minor version upgrades) (that's what the `-fabi-version=x` gcc compiler option is for). So having a matching standard library version is just one of the many things you need to worry about when it comes to abi compatibility. – Turtlefight Mar 14 '23 at 18:33
  • 1
    @Raven _"There can be more than one definition in a __program__ of each of the following: class type, enumeration type, ... as long as all of the following is true: ... __*__ each definition consists of the __same sequence of tokens__ (typically, appears in the same header file)..."_ 2 Standard Libraries breaks this rule. – Richard Critten Mar 14 '23 at 18:35

0 Answers0