Wherefore inline unnamed namespaces?
Asked Answered
O

2

29

A quick one for the gurus: C++11 allows unnamed namespaces to be declared inline. This seems redundant to me; things declared in an unnamed namespace are already used as if they were declared in the enclosing namespace.

So my question is this: what does it mean to say

inline namespace /*anonymous*/ {
    // stuff
}

and how is it different from the traditional

namespace /*anonymous*/ {
    // stuff
}

that we know and love from C++98? Can anyone give an example of different behaviour when inline is used?

EDIT: Just to clarify, since this question has been marked as a duplicate: I'm not asking about named inline namespaces in general. I understand the use-case there, and I think they're great. I'm specifically asking what it means to declare an unnamed namespace as inline. Since unnamed namespaces are necessarily always local to a TU, the symbol versioning rational doesn't seem to apply, so I'm curious about what adding inline actually does.


As an aside, the standard [7.3.1.1], regarding unnamed namespaces, says:

inline appears if and only if it appears in the unnamed-namespace-definition

but this seems like a tautology to my non-language lawyer eyes -- "it appears in the definition iff it appears in the definition"! For bonus points, can anyone explain what this bit of standardese is actually saying?

EDIT: Cubbi claimed the bonus point in the comments:

the standard is saying that unnamed-namespace-definition behaves as if it were replaced by X where inline appears in X iff it appears in the unnamed-namespace-definition

Oaf answered 26/11, 2013 at 4:35 Comment(7)
possible duplicate of What are inline namespaces for?Plano
@Jefffrey, This is about unnamed inline namespaces.Painting
@chris, I think you can mix the definition of unnamed and inline namespaces to come up with the answer.Plano
@Jefffrey That question is regarding inline namespaces in general, which I understand. This question is specifically asking what it means for an unnamed namespace to be inline, which doesn't seem to be covered by the linked answers (or any other SO question I could find).Oaf
The bonus point is easy: the standard is saying that unnamed-namespace-definition behaves as if it were replaced by X where inline appears in X iff it appears in the unnamed-namesace-definitionTaishataisho
@Taishataisho That actually makes sense, and probably would have clicked if I'd thought about it some more, rather than just reading it and going "huh?". Thanks, have yourself a bonus point! :-)Oaf
@Jefffrey if you can mix the definitions and come up an answer then please post it, because this is precisely what I'm asking! :-)Oaf
I
9

Here is one use that I have found:

namespace widgets { inline namespace {

void foo();

} } // namespaces

void widgets::foo()
{
}

In this example, foo has internal linkage and we can define the function later on by using the namespace::function syntax to ensure that the function's signature is correct. If you were to not use the widgets namespace then the void foo() definition would define a totally different function. You also don't need to re-open the namespace saving you a level of indentation.

If there is another function called foo in the widgets namespace already then this will give you an ambiguity instead rather than a nasty ODR violation.

Intervocalic answered 26/11, 2013 at 8:35 Comment(7)
I'm not sure I understand what you're doing here. Why is the inner inline namespace necessary?Urogenous
@Urogenous the inner inline namespace gives foo internal linkage. The outer namespace is so that you can use the namespace::function syntax to define it, ensuring you get the signature correct.Intervocalic
Ah, that makes sense. You might want to update your answer to explicitly indicate this, since I didn't pick that up the first time around.Urogenous
Cool, I like this! Clang doesn't seem to though: I get "out-of-line definition of 'foo' does not match any declaration in namespace 'widgets'". It works just fine with g++ though, so maybe it's just a Clang bug.Oaf
@TristanBrindle: Is that this Clang bug?Wicklund
I agree this is useful, but is the inline actually necessary here? It seems like it will work the same way without keyword inline.Spencerspencerian
@NirFriedman without the inline you can't define the foo function without opening the unnamed namespace again.Intervocalic
O
18

I don't know whether it's the done thing to answer your own question on SO, but after some playing around my curiosity has been satisfied, so I may as well share it.

The definition of an inline namespace includes not only the hoisting of names into the enclosing namespace (which happens anyway for unnamed namespaces), but also allows templates defined within an inline namespace to be specialised outside it. It turns out that this applies to unnamed namespaces too:

inline // comment this out to change behaviour
namespace { 
    template <typename T> struct A {};
}

template <> struct A<int> {};

Without the inline, g++ complains about trying to specialise a template from a different namespace (though Clang does not). With inline, it compiles just fine. With both compilers, anything defined within the specialisation is still marked as having internal linkage (according to nm), as if it were within the unnamed namespace, but I guess this is to be expected. I can't really think of any reason why this would be useful, but there we go.

An arguably more useful effect comes from the change regarding argument-dependent lookup for inline namespaces, which also affects unnamed inline namespaces. Consider the following case:

namespace NS {
    // Pretend this is defined in some header file
    template <typename T>
    void func(const T&) {}

    // Some type definition private to this TU
    inline namespace {
        struct A {};
    }

} // end namespace NS

int main()
{
    NS::A a;
    func(a);
}

Without inline, ADL fails and we have to explicitly write NS::func(a). Of course, if we defined the unnamed namespace at the toplevel (as one normally would), then we wouldn't get ADL whether it was inline or not, but still...

Oaf answered 26/11, 2013 at 8:41 Comment(0)
I
9

Here is one use that I have found:

namespace widgets { inline namespace {

void foo();

} } // namespaces

void widgets::foo()
{
}

In this example, foo has internal linkage and we can define the function later on by using the namespace::function syntax to ensure that the function's signature is correct. If you were to not use the widgets namespace then the void foo() definition would define a totally different function. You also don't need to re-open the namespace saving you a level of indentation.

If there is another function called foo in the widgets namespace already then this will give you an ambiguity instead rather than a nasty ODR violation.

Intervocalic answered 26/11, 2013 at 8:35 Comment(7)
I'm not sure I understand what you're doing here. Why is the inner inline namespace necessary?Urogenous
@Urogenous the inner inline namespace gives foo internal linkage. The outer namespace is so that you can use the namespace::function syntax to define it, ensuring you get the signature correct.Intervocalic
Ah, that makes sense. You might want to update your answer to explicitly indicate this, since I didn't pick that up the first time around.Urogenous
Cool, I like this! Clang doesn't seem to though: I get "out-of-line definition of 'foo' does not match any declaration in namespace 'widgets'". It works just fine with g++ though, so maybe it's just a Clang bug.Oaf
@TristanBrindle: Is that this Clang bug?Wicklund
I agree this is useful, but is the inline actually necessary here? It seems like it will work the same way without keyword inline.Spencerspencerian
@NirFriedman without the inline you can't define the foo function without opening the unnamed namespace again.Intervocalic

© 2022 - 2024 — McMap. All rights reserved.