具有相同名称但不同范围(例如 foo、bar::foo)的命名空间如何工作?

How do namespace's with same name but different scope (e.g. foo, bar::foo) work?

如果有两个命名空间FooBar,并且Bar里面有一个命名空间Foo。如果我从 Bar 中引用变量 Foo::i,它将在 FooBar::Foo 中搜索 i。如果不是,当 Bar::Foo 中不存在 i 时,是否可以让编译器在两个命名空间中进行搜索?

更具体地说,在下面的示例中,我尝试从命名空间 a 中引用变量 i,而不是添加额外的 ::。我知道放置 :: 是可行的,我正在尝试查看是否有任何其他方法可以解决此问题。

#include <iostream>
#include <string>

namespace a {
    int i = 1;
}

namespace b {
    namespace a {
    }
    
    namespace c {
        int j = a::i; // Doesn't work, need to use ::a::i;
    }
}
int main()
{
  std::cout << b::c::j << "\n";
}

您可以在内部命名空间中显式声明要从外部命名空间使用的变量的 using 声明。 即对于您的示例,

namespace a {
    int i = 1;
}

namespace b {
    namespace a {
        using ::a::i; //inner one does not define its own
        int i2 = 2;   //inner one creates its own variable
    }

    namespace c {
        int j = a::i; // Doesn't work, need to use ::a::i;
    }
}

参见: https://en.cppreference.com/w/cpp/language/namespace#Using-declarations

如果您可以更改 b::a,那么您确实可以将 b::a 中的某些声明从 ::a 中用作后备:

namespace a {
    int i = 1;
    int j = 2;
}

namespace b {
    namespace a {
        namespace detail {
            using ::a::i; // Selectively bring declarations from ::a here
        }
        using namespace detail; // Make the names in detail available for lookup (but not as declarations).
        //int i = 2;
    }
    
    namespace c {
        int j = a::i; // Uses ::a::i
        // int k = a::j; // ERROR! We didn't bring ::a::j into b::a at all
    }
}

Here it is live.

取消注释 b::a::i 的声明将更改输出。由于正确的声明优先于命名空间 using 指令引入的名称。