基于参数的依赖名称查找

Dr.*_*Gut 7 c++ linkage dependent-name language-lawyer argument-dependent-lookup

在cppreference.com上的描述

模板中使用的从属名称的查找被推迟到知道模板参数为止,这时ADL会检查具有外部链接的函数声明,这些声明从模板定义上下文模板实例化上下文中可见。

与此相反,以下代码片段可以使用三个编译器(MSVC,clang和gcc)很好地进行编译:

template <class T>
void CallFoo ()
{
    Foo (T ());
}


class Apple {};


int main ()
{
    CallFoo<Apple> ();
}


static void Foo (Apple)
{
}
Run Code Online (Sandbox Code Playgroud)

Foo是以下内容中的从属名称CallFoo:它取决于模板参数T。但是,Foo尽管违反了上面引用的两个规则,但是编译器仍然可以找到该函数。

  • Foo从的定义或实例中都看不到的声明CallFoo,因为它位于两者之下。
  • Foo 有内部联系。

这三个编译器都不可能有错误。我可能误会了一些东西。您能详细说明一下吗?

Dav*_*ing 3

在 C++03 中,匿名命名空间的成员可以具有外部链接,尽管在其他翻译单元中是不可命名的。因此,人们认为可以static从依赖 ADL 中排除实际功能。在C++11中,匿名命名空间强加了内部链接,因此限制变得不合理。然而,尽管实施采用了新行为,并且在 2011 年立即提交了一个问题(如评论中所述),但该措辞仍然保留在两个地方,直到2019 年 3 月的N4810

至于函数的放置,这是具有多个实例化点的函数的产物,包括实例化它们的任何翻译单元的末尾(对 C++20 中的模块进行了轻微调整);如果实例化函数模板对于不同的选择产生不同的结果,则该程序格式错误,不需要诊断(也如注释中所述)。