2

该程序不编译 ( 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();,它就会编译。演示

两个版本都有错误。foo即使声明,也不接受任何参数。以下问题自提出。

  • 为什么一个版本可以编译,而另一个版本不行?
  • C++ 标准中是否有这样的规则?“如果编译器能够证明没有任何实例是格式正确的,它可以(但不是必须)在没有实例的情况下诊断错误。”

我的理论如下(正确吗?)。里面template_func N::foo同时是一个限定名和一个从属名。依赖名称的查找被推迟到模板的实例化。查找名称(如果成功)会导致将该名称的使用与该名称的声明联系起来。但是这个过程包括两个步骤(我们现在只考虑限定名称,看起来像一个函数调用):

  1. 在限定符的范围内查找名称(在此示例中,这意味着 namespace N)。这可能会找到多个名称,因为函数可以重载。
  2. 检查参数是否可以传递给找到的名称。这包括找到一个最佳匹配,如果有多个fooN. 这种方式的使用与N::foo声明相关联N::foo

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

4

1 回答 1

2

您的分析似乎是正确的,并且您的代码格式不正确,无论是否void foo();注释掉,都不需要诊断。

您正在寻找的标准部分是:

[temp.res.general]/6.1

该程序格式错误,不需要诊断,如果:

— 无法为模板生成有效的特化 ...

于 2021-03-20T22:29:40.787 回答