[英]C++ Nested `namespace` `using` Name Lookup Order of Preference
I was reading about using
-directives on cppreference.com and they had some code I couldn't figure out the order preference for name lookup. 我正在读关于using
上cppreference.com -directives和他们有一些代码,我无法弄清楚的名称查找顺序优先。
I have read about the the transitive property of using
-directives on paragraph 3 , unqualified_lookup#namespace scope , and scope#namespace_scope . 我已经阅读了关于在第3段using
-directives的传递属性 , unqualified_lookup#namespace scope和scope#namespace_scope 。 I also tried searching around on some other sites. 我也试过在其他一些网站上搜索。
If there is some more documentation you think I should read, please suggest them. 如果您认为我应该阅读更多文档,请提出建议。
Their code is the following: 他们的代码如下:
Don't spend too much time reading this code because I will be talking about my adapted version below. 不要花太多时间阅读这段代码,因为我将在下面讨论我的改编版本。
namespace A {
int i;
}
namespace B {
int i;
int j;
namespace C {
namespace D {
using namespace A; // all names from A injected into global namespace
int j;
int k;
int a = i; // i is B::i, because A::i is hidden by B::i
}
using namespace D; // names from D are injected into C
// names from A are injected into global namespace
int k = 89; // OK to declare name identical to one introduced by a using
int l = k; // ambiguous: C::k or D::k
int m = i; // ok: B::i hides A::i
int n = j; // ok: D::j hides B::j
}
}
I have adapted their code to print things out: 我已经调整了他们的代码来打印出来:
I put numbered questions as comments on ones I don't understand. 我把编号问题作为我不理解的问题的评论。 You do not have to answer all questions if you can explain the order or name lookup and you think I could answer the rest of the questions myself. 如果您可以解释订单或名称查找,并且您认为我可以自己回答其余问题,则无需回答所有问题。
If my questions are too confusing, can you instead try to explain each of the variable name lookups in cppreference's code above? 如果我的问题太混乱了,您可以尝试在上面的cppreference代码中解释每个变量名称查找吗?
#include <iostream>
using namespace std;
namespace A {
int b = 0;
int i = 1;
}
namespace B {
int b = 2;
int i = 3;
int j = 4;
namespace C {
namespace D {
// 1) Why does cppreference say A is injected into `global`
// and not `D` namespace?
using namespace A; // all names from A injected into global namespace
int j = 5;
int k = 6;
int a = i; // i is B::i, because A::i is hidden by B::i
}
using namespace D; // names from D are injected into C
// 2) Why does cppreference say A is injected into `global` and
// not `C` namespace?
// names from A are injected into global namespace
int k = 7; // OK to declare name identical to one introduced by a using
// 3) What makes this ambiguous and not "one hides the other"?
// int l = k; // ambiguous: C::k or D::k
int m = i; // ok: B::i hides A::i
int n = j; // ok: D::j hides B::j
int c = b;
}
}
int main()
{
cout << "A::b " << A::b << endl; // prints "A::b 0"
cout << "A::i " << A::i << endl; // prints "A::i 1"
cout << endl;
cout << "B::b " << B::b << endl; // prints "B::b 2"
cout << "B::i " << B::i << endl; // prints "B::i 3"
cout << "B::j " << B::j << endl; // prints "B::j 4"
cout << endl;
cout << "B::C::a " << B::C::a << endl; // prints "B::C::a 3"
cout << "B::C::b " << B::C::b << endl; // prints "B::C::b 0"
cout << "B::C::c " << B::C::c << endl; // prints "B::C::c 2"
cout << "B::C::i " << B::C::i << endl; // prints "B::C::i 1"
cout << "B::C::j " << B::C::j << endl; // prints "B::C::j 5"
cout << "B::C::k " << B::C::k << endl; // prints "B::C::k 7"
cout << "B::C::m " << B::C::m << endl; // prints "B::C::m 3"
cout << "B::C::n " << B::C::n << endl; // prints "B::C::n 5"
cout << endl;
cout << "B::C::D::a " << B::C::D::a << endl; // prints "B::C::D::a 3"
cout << "B::C::D::b " << B::C::D::b << endl; // prints "B::C::D::b 0"
cout << "B::C::D::i " << B::C::D::i << endl; // prints "B::C::D::i 1"
cout << "B::C::D::j " << B::C::D::j << endl; // prints "B::C::D::j 5"
cout << "B::C::D::k " << B::C::D::k << endl; // prints "B::C::D::k 6"
cout << endl;
return 0;
}
Full Output: 全输出:
I put numbered questions as comments on ones I don't understand. 我把编号问题作为我不理解的问题的评论。
I suggest you open the above code side by side so you can see what I'm referencing. 我建议你并排打开上面的代码,这样你就可以看到我所引用的内容。 I kept lines < 80 chars. 我保持<80个字符。
A::b 0
A::i 1
B::b 2
B::i 3
B::j 4
B::C::a 3 // 4) cppreference says A::i == 1 is hidden by B::i == 3
// so this is == 3 and not 1.
// Why doesn't A::i hide B::i?
// Doesn't the `using namespace A` make A::i closer in scope
// than B::i?
// Why does this go up the parent blocks C->B->B::i == 3 and
// not up the namespaces C->D->A->A::i == 1?
B::C::b 0 // 5) This is == A::b == 0. This goes through the
// `using namespace D` which contains `using namespace A`.
// Why does this go up the namespaces C->D->A->A::b == 0 and
// not the parent blocks to C->B->B::b == 2 like in question 4?
B::C::c 2 // 6) This is == B::b == 2 (go up blocks C->B->B::b == 2).
// Why is it not == B::C:b == 0
// (go up namespaces C->D->A->A::b == 0 like in question 5)
// from the assignment `int c = b`?
// I'm guessing because name lookup for b
// inside the namespace body is different than the B::C::b lookup
// outside of the namespace body.
B::C::i 1 // 7) Compared to question 9 below, i is assigned to m but 1 != 3.
// I think this is similar to question 6 where name lookup
// outside of the namespace body is different than inside.
// I'm not sure why this goes up namespaces C->D->A->A::i == 1
// and not blocks C->B->B::i == 3.
B::C::j 5 // 8) Why does it go up namespaces C->D->D::j and not blocks
// C->B->B::j == 4?
B::C::k
B::C::m 3 // 9) cppreference says B::i hides A::i so this is == B::i == 3
// Why does this go up blocks C->B->B::i == 3 and not namespaces
// C->D->A->A::i == 1?
// Actually, I guess questions 9 and 7 is the same situation as
// questions 6 and 5, respectively. Where m and i corresponds
// with c and b, respectively.
B::C::n 5 // 10) cppreference says D::j hides B::j so this is == D::j == 5
// Why does this go up namespaces C->D->D::j == 5 and not
// blocks C->B->B::j == 4? The only difference I see between
// question 9 and 10 is that for question 9, i isn't declared
// within D like j is.
B::C::D::a 3 // 11) cppreference says A::i is hidden by B::i so
// this == B::i == 3. Why does this go up the blocks
// D->C->B->B::i == 3 instead of the
// namespaces D->A->A::i == 1?
// This goes up the blocks like question 9 but not
// up the namespaces like question 10.
B::C::D::b 0 // 12) This probably goes up the namespaces D->A->A::b == 0 and not
// blocks D->C->B->B::b == 2 because b is accessed
// outside the namespace body similar to questions 5, 7, and 8.
// Access inside the namespace body would be question 11 since
// the reference to i was captured inside a.
B::C::D::i 1 // 13) I think this is similar (~) to question 12 ~ 5, 7, and 8
// where it goes up namespaces D->A->A::i == 1 instead
// of blocks D->C->B->B::i == 3 because i is accessed outside
// of the namespace body.
B::C::D::j 5
B::C::D::k 6
List of questions that appeared above: 上面出现的问题列表:
global
and not D
namespace? 为什么cppreference说A被注入global
而不是D
命名空间? global
and not C
namespace? 为什么cppreference说A被注入global
而不是C
命名空间? using namespace A
make A::i closer in scope than B::i? using namespace A
是否使A :: i在范围上比B :: i更接近? Why does this go up the parent blocks C->B->B::i == 1 and not up the namespaces C->D->A->A::i == 3? 为什么这会上升到父块C-> B-> B :: i == 1而不是命名空间C-> D-> A-> A :: i == 3? using namespace D
which contains using namespace A
. 这是== A :: b == 0.这将通过using namespace D
,其中包含using namespace A
Why does this go up the namespaces C->D->A->A::b == 0 and not the parent blocks to C->B->B::b == 2 like in question 4? 为什么这会在命名空间C-> D-> A-> A :: b == 0上而不是像C-> B-> B :: b == 2的父块一样问题4? int c = b
? 这是== B :: b == 2.为什么它不是== B :: C:b == 0来自赋值int c = b
? I'm guessing because name lookup for b inside the namespace body is different than the B::C::b lookup outside of the namespace body. 我猜是因为命名空间体内的b的名称查找与命名空间体外的B :: C :: b查找不同。 // 1) Why does cppreference say A is injected into `global` // and not `D` namespace? using namespace A; // all names from A injected into global namespace
Because global is the nearest enclosing namespace that contains both A
and D
. 因为global是包含A
和D
的最近的封闭命名空间。 The effects of using namespace
are explained on that same page, just above the example using namespace
的效果在同一页面上解释,就在示例上方
using namespace D; // names from D are injected into C // 2) Why does cppreference say A is injected into `global` and // not `C` namespace? // names from A are injected into global namespace
Because global is the nearest enclosing namespace that contains both A
and C
因为global是包含A
和C
的最近的封闭命名空间
// 3) What makes this ambiguous and not "one hides the other"? // int l = k; // ambiguous: C::k or D::k
Because D::k
was pulled into C
by using namespace D;
因为D::k
通过using namespace D;
被拉入C
using namespace D;
, and the effects of that are also explained just above the example. ,以及其效果也在示例上方进行了解释。
Why doesn't A::i hide B::i? 为什么A :: i不隐藏B :: i? Doesn't the using namespace A make A::i closer in scope than B::i? 使用命名空间A是否使A :: i在范围上比B :: i更接近?
As noted above, using namespace A;
如上所述, using namespace A;
pulled A::i into global namespace (when viewed from within that block). 将A :: i拉入全局命名空间(从该块中查看)。 B::i
is "closer in scope" than the global namespace. B::i
比全局命名空间“更接近范围”。
In general, cppreference examples on language reference pages apply to the direcly preceding blocks of text, but it appears your main stumbling block is refusing to believe that using namespace A;
一般来说,语言参考页面上的cppreference示例适用于前面的文本块,但看起来你的主要障碍是拒绝相信using namespace A;
that appears within the unrelated namespace D
injects A's declarations into the global namespace. 出现在不相关的命名空间内的D
将A的声明注入全局命名空间。 That's really what it does. 这就是它的功能。 That's what it's for. 这就是它的用途。
The C++17 standard (draft here ), [basic.lookup.unqual], reads: C ++ 17标准( 这里草案),[basic.lookup.unqual],读作:
The declarations from the namespace nominated by a using-directive become visible in a namespace enclosing the using-directive [and] are considered members of that enclosing namespace. 来自using-directive提名的命名空间的声明在包含using-directive [和]的命名空间中变得可见,被认为是该封闭命名空间的成员。
Later in the C++17 standard, [namespace.udir] reads: 后来在C ++ 17标准中,[namespace.udir]读取:
A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive . using-directive指定指定命名空间中的名称可以在using-directive出现在using-directive之后的范围内使用 。 During unqualified name lookup, the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace. 在非限定名称查找期间,名称看起来好像是在最近的封闭命名空间中声明的,该命名空间同时包含using-directive和指定的命名空间。 Note: In this context, "contains" means "contains directly or indirectly". 注意:在此上下文中,“包含”表示“直接或间接包含”。 — end note - 结束说明
These might at least partly answer your question. 这些可能至少部分回答了你的问题。
Your sample code is thorough. 您的示例代码是彻底的。 If a less thorough but briefer sample code would also serve to illustrate, then try this: 如果一个不那么透彻但更简洁的示例代码也可以用来说明,那么试试这个:
#include <iostream>
namespace Your {
int f(const int n) {return 10*n;}
}
namespace My {
int f(const int n) {return 100*n;}
namespace Our {
using namespace Your;
int g() {return f(42);} // lookup from here
}
}
int main()
{
std::cout << My::Our::g() << "\n";
return 0;
}
Output after compilation by GCC 6.3: 4200
. GCC 6.3: 4200
编译后的输出。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.