[Development] inline namespaces as a versioning tool (was: Re: QList)

Marc Mutz marc.mutz at kdab.com
Thu Mar 30 11:08:45 CEST 2017


On Thursday 30 March 2017 08:41:51 Olivier Goffart wrote:
> On Donnerstag, 30. März 2017 08:32:24 CEST Marc Mutz wrote:
> > On Thursday 30 March 2017 08:18:52 Olivier Goffart wrote:
> > > On Donnerstag, 30. März 2017 07:20:11 CEST Marc Mutz wrote:
> > > > On Wednesday 29 March 2017 22:12:30 Thiago Macieira wrote:
> > > > > On quarta-feira, 29 de março de 2017 11:11:58 PDT Marc Mutz wrote:
> > > > > > Keyword: inline namespaces. This is the C++ mechanism for API
> > > > > > versioning. It allows to make that totally transparent. Why you
> > > > > > find that so odd as to be lacking for words is beyond me.
> > > > > 
> > > > > Inline namespaces do not solve the binary compatibility problem.
> > > > > They should not be used in Qt API for versioning.
> > > > > 
> > > > > Instead, do what you said before: create a V2 class.
> > > > 
> > > > Since the two are totally identical, except that inline namespaces
> > > > are transparent to the user, please explain what leads you to this
> > > > distinction.
> > > 
> > > Library 1:
> > >  inline namespace v1 { class Foo {}; }
> > > 
> > > Library 2:
> > >  LIBRARY2_EXPORT void registerPlugin(Foo*);
> > >  
> > >     -> symbol gets mangled as "registerPlugin(v1::Foo*)"
> > > 
> > > Application:
> > >   registerPlugin(new Foo);
> > >   
> > >      -> calls exported symbol "registerPlugin(v1::Foo*)"
> > > 
> > > When Library 1 puts Foo in the v2 inline namespace,  recompile Library2
> > > and
> > > the exported symbol becomes "registerPlugin(v2::Foo*)". If Application
> > > is not recompiled, it will not work as the old symbol is no longer
> > > found.
> > 
> > Well, of couse. That's like removing the QFoo overload when you add
> > QFooV2. Don't do that. You need to keep the v1::Foo definition as well
> > as the v1::Foo overload, just as you need to keep the QFoo definition
> > and the QFoo overload, when you add v2.
> 
> What I meant is that Library 1 becomes, in its next version
> 
>  namespace v1 { class Foo{}; }
>  inline namespace v2 { class Foo{}; }
> 
> It keeps  v1::Foo,  but puts v2::Foo in the inline namespace.
> 
> If you don't use "inline namespace v2", that means users needs to
> explicitly use v2::Foo to use the new features. So it is no longer
> "transparent to the user"

Ok, no.

library V1:

    inline // this inline is optional for V1 - users with compilers without
           //  support for them need to write v1:: explicitly, or it can be
           // reasonably emulated with a ...
    namespace v1 { class Foo{ int i, }; }
           // ... using v1::Foo, here
    LIB_EXPORT void useFoo(Foo);  // actually v1::Foo

user V1:

    useFoo(Foo{});  // actually v1::Foo

library V2:

    namespace v1 { class Foo{ int i; } } // from V1 of library
    inline
    namespace v2 { class Foo{ v1::Foo f; double d; } // adds a double member,
                                                     // reuses v1::Foo
    LIB_EXPORT void useFoo(v1::Foo); // from V1 of library
    LIB_EXPORT void useFoo(Foo);     // actually v2::Foo

user V2 @ library V2:

    useFoo(Foo{}); // actually v2::Foo

user V1 @ library V2:

    (compiled and continuing to run as) useFoo(v1::Foo{});

-> totally transparent, BC and SC

Where's my mistake?

> Personally I prefer having a pimpl so I can just add or change members.
> 
> (Note that if the class is at least sizeof(void*) and that none of its
> member are accessed in inline methods or ctors/dtor, we can add a pimpl
> later, when we need it.)

The point is to have thin abstractions be completely inline. QSizePolicy is a 
good example. It's full now. If ever we need to add a new member, we need 
QSizePolicyV2.

Note that I'm not saying that we should version QString or other such core 
classes like this. This is completely impractical. But we have tons of small 
classes that are used in only a handful of APIs and they would definitely 
benefit from this. QStyleOption, QSizePolicy, most QSsl value types. Stuff 
like Q*DialogOptions. There's just no reason to pay the pimpl price for these 
anymore.
 
Thanks,
Marc

-- 
Marc Mutz <marc.mutz at kdab.com> | Senior Software Engineer
KDAB (Deutschland) GmbH & Co.KG, a KDAB Group Company
Tel: +49-30-521325470
KDAB - The Qt, C++ and OpenGL Experts



More information about the Development mailing list