Search code examples
c++c++11abibinary-compatibility

Can inline namespaces be used to keep backwards compatibility in a shared library?


The rationale for C++'s inline namespaces is both source and binary compatibility (see Herb Sutter's paper linked in N2535), but I have not been able to find good examples of keeping binary compatibility for existing libraries when introducing inline namespaces, or if it is possible.

(for more info, and examples of source compatibility, see this question)

(for solving a related problem, using inline namespace to introduce incompability, see this question)

If this is our current library (e.g. mylib.dll), which is shared with clients and need to be stable:

struct ModelA
{
   /* (...) lots of stuff */
};

struct ModelB
{
   /* (...) lots of stuff */
};

Can we use inline namespaces to introduce new versions of the structs/classes without breaking the clients (i.e. replace the shared library file (mylib.dll) only, no recompile neccessary)?

inline namespace mylib
{

inline namespace v1
{
struct ModelA
{
   /* (...) lots of stuff */
};
} // end namespace v1

namespace v2
{
struct ModelA
{
   /* (...) lots of stuff + newstuff */
};
} // end namespace v2

struct ModelB
{
   /* (...) lots of stuff */
};

} // end namespace mylib

If not, will it work without the enclosing inline namespace mylib?


Solution

  • Not really an answer to your question, but probably can lead to an answer.

    Tested under gcc 4.8.2 with two simple sources:

    namespace n1
    {
       void f1 (int);
    
       inline namespace n2
       {
          void f2 (int);
       }
    }
    
    void f (int x)
    {
       n1::f1(x);
       n1::f2(x);
    }
    

    And without inline namespace:

    namespace n1
    {
       void f1 (int);
       void f2 (int);
    }
    
    void f (int x)
    {
       n1::f1(x);
       n1::f2(x);
    }
    

    Then inspected mangled names of symbols in compiled object files using objdump -t.

    Results for the first version (with inline namespace):

    _ZN2n12f1Ei
    _ZN2n12n22f2Ei
    

    Second version (without inline namespace):

    _ZN2n12f1Ei
    _ZN2n12f2Ei
    

    You can see that the mangled name of f2 differs (the first one includes the name of n2 namespace). It means that in case you are using gcc, you cannot just replace your library with a new one with inlined namespaces. I won't expect that some other compiler will do it another way (save binary compatibility with inline namespaces).