Search code examples
c++c++11namespacesinline-namespaces

How can I explicitly refer to an enclosing namespace when an inline namespace exists?


Please consider this code:

#include <iostream>

namespace Foo{

    void ool()  // Version A
    {
        std::cout << "Foo::ool" << std::endl;
    }

    inline namespace Bar{
        void ool() // Version B
        {
            std::cout << "Foo::Bar::ool" << std::endl;
        }
    }
}


int main()
{
    Foo::ool();  // <- error
}

Both Clang and G++ correctly mark Foo::ool as ambiguous. I can call Foo::Bar::ool without problem but is there a way to call the version A without changing its declaration?

I found people in similar position trying to understand what happens but I did not see a solution for this case.

I am in this situation because I have a project that includes a declaration of std::__1::pair and std::pair, made in different places, with std::__1 being an inline namespace. I need the code to point to the std::pair explicitly. Is there a solution for that?


Solution

  • I don't think that is possible; from cppreference:

    Qualified name lookup that examines the enclosing namespace will include the names from the inline namespaces even if the same name is present in the enclosing namespace.

    However, it seems you are not actually in the situation you describe, as you say that the two definitions are pulled from different files. Thus you "bookmark" the more external definition in order to be able to call it when you need it:

    #include <iostream>
    
    // Equivalent of first include
    namespace Foo{
        void ool()  // Version A
        {
            std::cout << "Foo::ool" << std::endl;
        }
    }
    
    const auto& foo_ool = Foo::ool;
    
    // Equivalent of second include
    namespace Foo{
        inline namespace Bar{
            void ool() // Version B
            {
                std::cout << "Foo::Bar::ool" << std::endl;
            }
        }
    }
    
    int main()
    {
        foo_ool(); // Works
    }
    

    If the thing you want to bookmark is a type, a simple using directive should suffice. The equivalent code for you would look like:

    #include <my_first_include>
    
    // bookmark code
    
    #include <my_second_include>
    
    // rest of the code