1

Reading and researching a lot about the new C++11 feature - "inline namespace" I don't understand what the real benefit of this feature is.

I could easily have all the functions/types which are defined in an "inline namespace" placed directly in the enclosing one and have the same result. So what is the real motivation of placing functions/types in an inline namespace? Grouping the functions/types? Is there any ADL related benefit in using "inline namespace"? I thought ADL would behave the same was as there was an implicit "using" directive for this "inline namespace."

EDIT1:

So I think the following is the key advantage. Let's say initially we have this:

namespace toplevel {
     // Users can use toplevel::MyType
     inline namespace current {
           class MyType {};
     } // inline namespace current
} // ns toplevel

Now, some new requirements, and we need a new version to be available but keep the old one intact:

namespace toplevel {
     // Users can use toplevel::MyType
     // we can let the users know that we are going to deprecate it
     // in favor of toplvel::next::MyType
     inline namespace current {
           class MyType {};
     } // inline namespace current

     // Users can use toplevel::next::MyType
     namespace next {
           class MyType {};
     } // namespace next

} // ns toplevel

And finally do this. Move inline to the "next" namespace making it the default. Still letting the users access to "current" but with explicit ::current - i.e. this way: toplevel::current::MyType BTW - my preference would even rename "current" to "deprecated".

namespace toplevel {
     // Users can still use it by referring
     // to toplevel::current::MyType
     namespace current {
           class MyType {};
     } // inline namespace current

     // Have this one the default one 
     // under toplevel
     // Users can use the new one this way: toplevel::MyType
     inline namespace next {
           class MyType {};
     } // namespace next

} // ns toplevel

Does it sound like a correct scenario?

Kobi
  • 832
  • 1
  • 9
  • 16
  • 1
    Name mangling and versionable linking are some of the main motivations. – Kerrek SB Apr 15 '17 at 00:00
  • Possible duplicate of [What are inline namespaces for?](http://stackoverflow.com/questions/11016220/what-are-inline-namespaces-for) – Miles Budnek Apr 15 '17 at 00:07
  • OK. so versioning is indeed one of the main motivation. Reading [what-are-inline-namespaces-for](http://stackoverflow.com/questions/11016220/what-are-inline-namespaces-for) again, I think the idea is to be able to give something default like std::vector, but allow the users to be able to fall back to std::pre_cxx_1997::vector if newer compiler's std libc++'s vector is not working well. So I guess this nice feature is the key advantage for using lnline. I'll edit my question. – Kobi Apr 15 '17 at 04:27

1 Answers1

4

The main motivation for C++ inline namespaces does indeed involve versioning. You are on the right track with your understanding, except for the final sentence in your question:

My preference would even rename "current" to "deprecated"

The whole idea of using inline namespaces is that the namespace names aren't changing -- rather, this feature allows for the namespace names to not need to change; existing names can live on forever without requiring much change to code.

Instead, at the time a version release is made (when what we used to think of as "current features" now become "deprecated features"), the namespace names can stay the same but their default status gets updated.

Let's see this in code:

namespace MyProject {
    namespace Version1 {
        void BoringStableFunction() {...}
    }
    inline namespace Version2 {
        void BoringStableFunction() {...}
        void LatestAndGreatest(int x) {...}
    }
}

The clients of this software probably will most often be using it by simply calling MyProject::BoringStableFunction() and maybe MyProject::LatestAndGreatest(11), perhaps without even knowing that two separate versions of MyProject exist. And that convenience can be a good thing. If a client does know that there were two different versions, and intentionally wants to use the old one (before LatestAndGreatest() had been invented), he can still do so by calling MyProject::Version1::BoringStableFunction().

Note that a client is allowed to write his code as MyProject::Version2::BoringStableFunction(). Doing so is the client essentially saying "I want to call that current #2 version, and I want that implementation which I'm using to stay the same -- even if that MyProject project gets updated later on"

Notice how I can perform additional development without affecting any of my existing clients:

namespace MyProject {
    namespace Version1 {
        void BoringStableFunction() {...}
    }
    inline namespace Version2 {
        void BoringStableFunction() {...}
        void LatestAndGreatest(int x) {...}
    }
    namespace Version3 {
        void BoringStableFunction() {...}
        void LatestAndGreatest(std::string x) {...}
    }   
}

When I'm ready to release my changes to the general public, only this tiny edit needs to be made:

namespace MyProject {
    namespace Version1 {
        void BoringStableFunction() {...}
    }
    namespace Version2 {
        void BoringStableFunction() {...}
        void LatestAndGreatest(int x) {...}
    }
    inline namespace Version3 {
        void BoringStableFunction() {...}
        void LatestAndGreatest(std::string x) {...}
    }   
}

Most of the clients had been calling MyProject::BoringStableFunction(). Their code won't need to be edited; it is still syntactically valid. But they will now suddenly be taking advantage of any new implementation that I might have changed within BoringStableFunction().

If they had been so bold as to be using my MyProject::LatestAndGreatest(11), they will need to be informed that they now need to update their usage. So this demonstrates that, even with inline namespaces, thought still needs to be put into the contract between a programmer and his client.

Cow Corporation
  • 399
  • 2
  • 7