【问题标题】:Argument-dependent lookup of dependent names依赖名称的参数依赖查找
【发布时间】:2019-08-26 18:33:45
【问题描述】:

This description on cppreference.com 这么说

模板中使用的依赖名称的查找被推迟,直到模板参数已知,此时 [...] ADL 检查具有 外部链接 的函数声明,这些声明可从任一模板定义上下文模板实例化上下文

与此相反,以下代码 sn-p compiles fine 带有三个编译器(MSVC、clang、gcc):

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


class Apple {};


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


static void Foo (Apple)
{
}

FooCallFoo 中的从属名称:它依赖于模板参数T。但是函数Foo尽管违反了上面引用的两条规则,但还是被编译器发现了。

  • Foo 的声明在 CallFoo 的定义或实例化中均不可见,因为它位于两者之下。
  • Foo 有内部链接。

这三个编译器都不太可能有错误。我可能误会了什么。你能详细说明一下吗?

【问题讨论】:

  • 我有一个类似的问题,添加了constexpr。见here,
  • N4713 没有提到与参数相关的名称查找的“外部链接”。我认为您在 cppreference.com 站点中发现了一个措辞错误。
  • 不是病态,不需要诊断吗? (所以所有编译器都是正确的:))。对于实现,我认为他们使用 and of file 作为实例化,所以他们找到了。
  • 我不知道是否有其他规则生效,但是使用匿名命名空间(这也应该使内部链接?)确实会失败,无论你把它放在哪里(在定义 @987654334 @ 当然)。
  • @Eljay 闻起来像 CWG1258

标签: c++ language-lawyer linkage argument-dependent-lookup dependent-name


【解决方案1】:

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

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

【讨论】:

  • “用于不同的选择”——您的意思是“用于不同的实例化点”吗?我的例子不正确吗?在CallFoo Foo 中不可见。在文件的末尾。
  • @Dr.Gut:是的,这就是这里的“选择”。是的,该代码是格式错误的 NDR,因为重载解析的结果取决于实例化点(并且因为更好地匹配 is available)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
相关资源
最近更新 更多