普通查找和隐藏
Ordinary lookup and hiding
下面的程序可以编译(live demo),但我不明白,为什么。
namespace N {
struct S {};
}
void Foo(N::S);
namespace Lib {
template <class T>
void Call() { Foo(T{}); }
void Foo();
}
int main()
{
Lib::Call<N::S>();
}
Lib::Foo
不应该隐藏 ::Foo
吗? Call
中的 Foo
是依赖名称,依赖名称的评估应该推迟到模板实例化时进行。在这种情况下名称查找如何工作?
在命名空间Lib
中Foo(N::S{})
可以在void Foo();
的声明之前调用,但是不能在声明之后调用,因为Lib::Foo
隐藏了::Foo
]. Lib::Call<N::S>();
在声明之后,所以在这里绑定名字Foo
的时候,隐藏应该是生效的吧?
对模板中使用的名称的所有 non-ADL 查找都来自模板定义,即使在 ADL 可能起作用的情况下,在实例化之前 使用 结果也是如此从实例化上下文中找到的声明。
你可以从“空间”的角度来考虑这一点——依赖查找的两个部分同时发生在不同的地方(限制它们找到的内容)——或者从“时间”的角度来看——non-dependent-ADL 查找在解析模板时发生,结果被保存并在实例化期间与依赖的 ADL 结果合并。前者是标准描述它的方式(以避免将编译描述为 time-dependent 过程),但后者直观地解释了出于解析目的对依赖名称的处理(因此当 typename
和 template
是必需的)。
这方面的标准规则分散在不同类型名称的几种情况下([temp.res]/1.3, [temp.nondep]/1, and [temp.dep.candidate]/1 在 C++20 中)。
下面的程序可以编译(live demo),但我不明白,为什么。
namespace N {
struct S {};
}
void Foo(N::S);
namespace Lib {
template <class T>
void Call() { Foo(T{}); }
void Foo();
}
int main()
{
Lib::Call<N::S>();
}
Lib::Foo
不应该隐藏 ::Foo
吗? Call
中的 Foo
是依赖名称,依赖名称的评估应该推迟到模板实例化时进行。在这种情况下名称查找如何工作?
在命名空间Lib
中Foo(N::S{})
可以在void Foo();
的声明之前调用,但是不能在声明之后调用,因为Lib::Foo
隐藏了::Foo
]. Lib::Call<N::S>();
在声明之后,所以在这里绑定名字Foo
的时候,隐藏应该是生效的吧?
对模板中使用的名称的所有 non-ADL 查找都来自模板定义,即使在 ADL 可能起作用的情况下,在实例化之前 使用 结果也是如此从实例化上下文中找到的声明。
你可以从“空间”的角度来考虑这一点——依赖查找的两个部分同时发生在不同的地方(限制它们找到的内容)——或者从“时间”的角度来看——non-dependent-ADL 查找在解析模板时发生,结果被保存并在实例化期间与依赖的 ADL 结果合并。前者是标准描述它的方式(以避免将编译描述为 time-dependent 过程),但后者直观地解释了出于解析目的对依赖名称的处理(因此当 typename
和 template
是必需的)。
这方面的标准规则分散在不同类型名称的几种情况下([temp.res]/1.3, [temp.nondep]/1, and [temp.dep.candidate]/1 在 C++20 中)。