当内联命名空间存在时,如何显式引用封闭命名空间?

Yve*_*ner 24 c++ namespaces c++11 inline-namespaces

请考虑以下代码:

#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
}
Run Code Online (Sandbox Code Playgroud)

Clang和G ++都正确地标记Foo::ool为含糊不清.我可以Foo::Bar::ool毫无问题地打电话但有没有办法在不改变声明的情况下调用版本A?

我发现处于类似位置的人试图了解会发生什么,但我没有看到这种情况的解决方案.

我处于这种情况,因为我有一个项目,其中包含一个声明,std::__1::pairstd::pair在不同的地方,std::__1作为内联命名空间.我需要代码std::pair明确指向.有解决方案吗?

Sva*_*zen 12

我不认为这是可能的; 来自cppreference:

检查封闭命名空间的限定名称查找将包括内联命名空间中的名称,即使封闭命名空间中存在相同的名称也是如此.

但是,您似乎并没有真正处理您描述的情况,因为您说这两个定义是从不同的文件中提取的.因此,您可以"标记"更多的外部定义,以便能够在需要时调用它:

#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
}
Run Code Online (Sandbox Code Playgroud)

如果你想要书签的东西是一个类型,一个简单的using指令就足够了.您的等效代码如下所示:

#include <my_first_include>

// bookmark code

#include <my_second_include>

// rest of the code
Run Code Online (Sandbox Code Playgroud)


Ad *_*d N 5

一旦看到内联命名空间,就无法明确地引用封闭命名空间中定义的符号.

特别是对于你的情况,合格的查找main被正确地标记为含糊不清(正如你自己所说).请参阅cppreference的最后一点:

检查封闭命名空间的限定名称查找将包括内联命名空间中的名称,即使封闭命名空间中存在相同的名称也是如此.


然而,还有其他人在评论中指出,当您尝试使用时,您可能在工具链调用中遇到配置问题std::pair.

要解决您的问题,您需要确保调用编译器来编译C++ 11代码,该代码将带有标志:

-std=c++11-std=c++0x取决于您的Clang/GCC版本

进一步提供上下文:
内联命名空间是一个C++ 11特性,主要用于允许在库中进行符号版本控制.然后,C++标准库实现可以在嵌套命名空间中定义不同版本的符号(使用非标准名称),并且在编译时根据请求的库版本,工具链将这些嵌套命名空间中的一个定义为内联.看来你正在使用库的c ++ 11版本(因为它定义了一些符号,特别pair是在内联命名空间中_1),因此在内联命名空间中实际符合你想要的符号.