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

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

请考虑此代码:

#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
}

Clang 和 G++ 都正确地将 Foo::ool 标记为不明确。我可以毫无问题地调用 Foo::Bar::ool 但有没有办法在不更改其声明的情况下调用版本 A?

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

我遇到这种情况是因为我有一个项目包含 std::__1::pairstd::pair 的声明,这些声明是在不同的地方创建的,其中 std::__1 是一个内联命名空间。我需要代码明确指向 std::pair 。有解决办法吗?

当内联命名空间确实有同名方法 ool 时,我认为您不能含糊地引用 ool

不过你可以试试这个;

#include <iostream>

namespace Foo{

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

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


int main()
{
    Foo::ool();  // no error
}
  1. namespace Foo 中的方法包装在 namespace A 中,然后 inline namespace A
  2. Bar 中删除内联。

现在如果你调用 Foo::ool(); 它将调用 inline A::ool()
Bar::ool 可以被 Foo::Bar::ool

调用

一旦看到内联命名空间,就不能明确引用封闭命名空间中定义的符号。

特别是对于您的情况,main 中的限定查找被正确地标记为不明确(正如您自己所说)。请参阅 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.


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

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

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

版本

提供更多背景信息:
内联命名空间是 C++11 的一个特性,引入它主要是为了在库中允许 符号版本控制 。然后,C++ 标准库实现可以在嵌套命名空间(使用非标准名称)中定义不同版本的符号,并且根据编译时请求的库版本,工具链将这些嵌套命名空间之一定义为内联。看来您正在使用库的 c++11 版本(因为它在内联命名空间 _1 中定义了一些符号,特别是 pair),所以实际上在内联命名空间中有符号你要。

我不认为这是可能的;来自 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.

但是,您所说的这两个定义似乎是从不同的文件中提取的,实际上您描述的情况似乎并不如此。因此,您 "bookmark" 更多的外部定义,以便在需要时能够调用它:

#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
}

如果您要添加书签的是类型,一个简单的 using 指令就足够了。您的等效代码如下所示:

#include <my_first_include>

// bookmark code

#include <my_second_include>

// rest of the code