相关名称的参数相关查找
Argument-dependent lookup of dependent names
This description on cppreference.com 说
The lookup of a dependent name used in a template is postponed until the template arguments are known, at which time [...] ADL examines function declarations with external linkage that are visible from either the template definition context or the template instantiation context.
与此相反,以下代码片段 compiles fine 具有三个编译器(MSVC、clang、gcc):
template <class T>
void CallFoo ()
{
Foo (T ());
}
class Apple {};
int main ()
{
CallFoo<Apple> ();
}
static void Foo (Apple)
{
}
Foo
是 CallFoo
中的从属名称:它取决于模板参数 T
。但是尽管违反了上面引用的两个规则,编译器还是找到了函数 Foo
。
Foo
的声明在 CallFoo
的定义或实例化中都不可见,因为它在两者之下。
Foo
有内部链接。
三个编译器都存在错误的可能性不大。我可能误会了什么。你能详细说明一下吗?
在 C++03 中,匿名命名空间的成员可以具有外部链接,尽管在其他翻译单元中是不可命名的。因此,人们认为可以排除依赖 ADL 的实际 static
功能。在 C++11 中,匿名命名空间强加了内部链接,因此限制变得不合理。然而,尽管实施采用了新行为并在 2011 年立即提交了一个问题(如评论中所述),但直到 2019 年 3 月 N4810 之前,措辞仍保留在两个地方。
至于函数的放置,这是具有 multiple points of instantiation 的函数的产物,包括实例化它们的任何翻译单元的末尾(对 C++20 中的模块进行了轻微调整);如果实例化函数模板对不同的选择产生不同的结果,则程序格式错误,不需要诊断(如评论中所述)。
This description on cppreference.com 说
The lookup of a dependent name used in a template is postponed until the template arguments are known, at which time [...] ADL examines function declarations with external linkage that are visible from either the template definition context or the template instantiation context.
与此相反,以下代码片段 compiles fine 具有三个编译器(MSVC、clang、gcc):
template <class T>
void CallFoo ()
{
Foo (T ());
}
class Apple {};
int main ()
{
CallFoo<Apple> ();
}
static void Foo (Apple)
{
}
Foo
是 CallFoo
中的从属名称:它取决于模板参数 T
。但是尽管违反了上面引用的两个规则,编译器还是找到了函数 Foo
。
Foo
的声明在CallFoo
的定义或实例化中都不可见,因为它在两者之下。Foo
有内部链接。
三个编译器都存在错误的可能性不大。我可能误会了什么。你能详细说明一下吗?
在 C++03 中,匿名命名空间的成员可以具有外部链接,尽管在其他翻译单元中是不可命名的。因此,人们认为可以排除依赖 ADL 的实际 static
功能。在 C++11 中,匿名命名空间强加了内部链接,因此限制变得不合理。然而,尽管实施采用了新行为并在 2011 年立即提交了一个问题(如评论中所述),但直到 2019 年 3 月 N4810 之前,措辞仍保留在两个地方。
至于函数的放置,这是具有 multiple points of instantiation 的函数的产物,包括实例化它们的任何翻译单元的末尾(对 C++20 中的模块进行了轻微调整);如果实例化函数模板对不同的选择产生不同的结果,则程序格式错误,不需要诊断(如评论中所述)。