依赖限定名的查找
Lookup of dependent qualified names
此程序无法编译 (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
里面同时是限定名和从属名。依赖名称的查找被推迟到模板的实例化。查找名称(如果成功)会导致将该名称的使用与该名称的声明联系起来。但是这个过程包括两个步骤(现在让我们只考虑限定名称,看起来像一个函数调用):
- 在限定符的范围内查找名称(在本例中这意味着名称空间
N
)。这可能会找到多个名称,因为函数可以重载。
- 正在检查是否可以将参数传递给找到的名称。如果
N
中有多个 foo
,这包括找到最佳匹配。这样 N::foo
的使用与 N::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 ...
此程序无法编译 (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
里面同时是限定名和从属名。依赖名称的查找被推迟到模板的实例化。查找名称(如果成功)会导致将该名称的使用与该名称的声明联系起来。但是这个过程包括两个步骤(现在让我们只考虑限定名称,看起来像一个函数调用):
- 在限定符的范围内查找名称(在本例中这意味着名称空间
N
)。这可能会找到多个名称,因为函数可以重载。 - 正在检查是否可以将参数传递给找到的名称。如果
N
中有多个foo
,这包括找到最佳匹配。这样N::foo
的使用与N::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 ...