Wherefore inline unnamed namespaces?

后端 未结 2 1626
天涯浪人
天涯浪人 2021-02-12 06:09

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 us

相关标签:
2条回答
  • 2021-02-12 06:25

    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...

    0 讨论(0)
  • 2021-02-12 06:45

    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.

    0 讨论(0)
提交回复
热议问题