C++命名空间中的名称解析规则是什么?
What are the name resolution rules in C++ namespaces?
如何在 C++ 命名空间中解析名称?
我对以多种不同方式提供名称的情况特别感兴趣,例如通过父命名空间和 using namespace
。
拿这段代码来说:
namespace ns1 {
static auto str = "ns1::str";
}
namespace ns2 {
static auto str = "ns2::str";
namespace sub {
using namespace ns1;
auto f() { return str; }
}
}
使用我的编译器,ns2::sub::f()
returns "ns2::str"
。我预计它会 return "ns1::str"
,因为 using namespace ns1
出现在 ns2::sub
.
现在这首曲子:
static auto str = "str";
namespace ns1 {
static auto str = "ns1::str";
}
namespace ns2 {
using namespace ns1;
auto f() { return str; }
}
我预计它会像之前的案例那样运行。相反,它不编译:
error: reference to ‘str’ is ambiguous
这背后的逻辑是什么?
使用指令要牢记以下规则
[namespace.udir]
2 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. During unqualified name lookup
([basic.lookup.unqual]), the names appear as if they were declared in
the nearest enclosing namespace which contains both the
using-directive and the nominated namespace. [ Note: In this context,
“contains” means “contains directly or indirectly”. — end note ]
3 A using-directive does not add any members to the declarative
region in which it appears.
第 3 段确保我们在尝试 名称查找之前不会收到错误。它不添加声明,只要 str
不被非限定名称查找查找,我们就不会发生冲突。而第 2 段告诉我们名称的逻辑布局方式。我们可以将其应用于您的两个示例。
包含 using namespace ns1;
和命名空间 ns1
本身的最近的封闭命名空间是全局命名空间。所以名称 ns1::str
的行为就好像我们写了
static auto str = "ns1::str";
namespace ns2 {
static auto str = "ns2::str";
namespace sub {
auto f() { return str; }
}
}
因此,名称查找只会找到 ns2::str
,因为它会隐藏命名空间中的任何 str
和封闭的命名空间(这是上面代码中的“假设”情况)。
同样,最近的封闭命名空间是全局命名空间。但是这一次,我们得到的布局是不同的
static auto str = "str"; // This is the one declared
static auto str = "ns1::str"; // This is the one "as-if" made available
namespace ns2 {
auto f() { return str; }
}
显然,上面的“等效”代码片段无效,声明会相互冲突。但它是冲突根源的例证。来自该范围的名称存在冲突。所以不合格的名称查找失败。
在没有使用指令的情况下,非限定名称查找的行为相当直观。范围从内到外查找,直到找到名称声明。
如何在 C++ 命名空间中解析名称?
我对以多种不同方式提供名称的情况特别感兴趣,例如通过父命名空间和 using namespace
。
拿这段代码来说:
namespace ns1 {
static auto str = "ns1::str";
}
namespace ns2 {
static auto str = "ns2::str";
namespace sub {
using namespace ns1;
auto f() { return str; }
}
}
使用我的编译器,ns2::sub::f()
returns "ns2::str"
。我预计它会 return "ns1::str"
,因为 using namespace ns1
出现在 ns2::sub
.
现在这首曲子:
static auto str = "str";
namespace ns1 {
static auto str = "ns1::str";
}
namespace ns2 {
using namespace ns1;
auto f() { return str; }
}
我预计它会像之前的案例那样运行。相反,它不编译:
error: reference to ‘str’ is ambiguous
这背后的逻辑是什么?
使用指令要牢记以下规则
[namespace.udir]
2 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. During unqualified name lookup ([basic.lookup.unqual]), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace. [ Note: In this context, “contains” means “contains directly or indirectly”. — end note ]
3 A using-directive does not add any members to the declarative region in which it appears.
第 3 段确保我们在尝试 名称查找之前不会收到错误。它不添加声明,只要 str
不被非限定名称查找查找,我们就不会发生冲突。而第 2 段告诉我们名称的逻辑布局方式。我们可以将其应用于您的两个示例。
包含
using namespace ns1;
和命名空间ns1
本身的最近的封闭命名空间是全局命名空间。所以名称ns1::str
的行为就好像我们写了static auto str = "ns1::str"; namespace ns2 { static auto str = "ns2::str"; namespace sub { auto f() { return str; } } }
因此,名称查找只会找到
ns2::str
,因为它会隐藏命名空间中的任何str
和封闭的命名空间(这是上面代码中的“假设”情况)。同样,最近的封闭命名空间是全局命名空间。但是这一次,我们得到的布局是不同的
static auto str = "str"; // This is the one declared static auto str = "ns1::str"; // This is the one "as-if" made available namespace ns2 { auto f() { return str; } }
显然,上面的“等效”代码片段无效,声明会相互冲突。但它是冲突根源的例证。来自该范围的名称存在冲突。所以不合格的名称查找失败。
在没有使用指令的情况下,非限定名称查找的行为相当直观。范围从内到外查找,直到找到名称声明。