c++ - 依赖限定名的查找

标签 c++ name-lookup dependent-name qualified-name

此程序无法编译 ( error: 'foo' is not a member of 'N' ):

namespace N {
//    void foo();
}

template<class T>
void template_func(T t) {
    N::foo(t);
}
但是如果我们取消注释 void foo(); 的声明,它编译。 Demo .
两个版本都有错误。 foo即使声明,也不接受任何参数。下面的问题提出了自己。
  • 为什么编译一个版本,而不编译另一个?
  • C++ 标准中是否有这样的规则? “如果编译器能够证明没有实例化可以是格式良好的,它可以(但不需要)在没有实例化的情况下诊断错误。”

  • 我的理论如下(是否正确?)。内template_func N::foo同时是限定名和从属名。依赖名称的查找被推迟到模板的实例化。查找名称(如果成功)会导致将该名称的使用与该名称的声明联系起来。但是这个过程包括两个步骤(让我们现在只考虑限定名称,看起来像一个函数调用):
  • 在限定符的范围内查找名称(在此示例中,这意味着 namespace N )。这可能会找到多个名称,因为函数可以被重载。
  • 检查参数是否可以传递给找到的名称。这包括寻找最佳匹配,如果不止一个 fooN .这种方式使用N::fooN::foo 相关联宣言。

  • 实际上第一步可以在没有实例化的情况下完成。编译器好像做了,如果没有foo找到后,它会诊断错误(这是可选的)。如果至少有一个 foo发现它不打扰进一步分析。

    最佳答案

    您的分析似乎是正确的,并且您的代码格式错误,无需诊断,无论 void foo(); 是否正确是否被注释掉。
    您正在寻找的标准部分是:

    [temp.res.general]/6.1

    The program is ill-formed, no diagnostic required, if:

    — no valid specialization can be generated for a template ...

    关于c++ - 依赖限定名的查找,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66727031/

    相关文章:

    c++ - 使用 std::regex 调用 abort() 来验证 URL

    c++ - 使用#ifdef 检测编译器

    c++ -::(范围解析运算符) 前面没有任何内容

    c++ - 为什么在使用 "using namespace std;"和 "bits/stdc++.h"时会在此代码中出现错误?

    c++ - 允许 `this->` 访问依赖基类的成员的规则是什么?

    c++ - 为什么必须在哪里放置 “template”和 “typename”关键字?

    c++ - 为什么我不能将指定的初始化程序与不是聚合的结构一起使用?

    c++ - std::vector 类型引用的无效初始化

    c++ - 函数、类和变量都具有相同的名称

    c++ - 为什么必须在何处以及为什么要放置"template"和"typename"关键字?