以下C ++代码无法编译,例如用g ++ - 4.7或clang ++ - 3.2:
struct Bar {};
template<typename T>
void foo(T t, Bar bar) {
t.compiler_does_not_care();
bar.nonexistent_method();
}
int main() {}
为什么编译器检查模板函数foo的代码是否具有语义正确性(他们可以在哪里),即使它从未实例化过?这个标准是否合规?
答案 0 :(得分:7)
Bar
是非依赖名称(即其类型不依赖于T
),因此编译器需要在名称查找的第一阶段验证代码的正确性(请参阅下面的说明)。
由于Bar
没有nonexistent_method()
方法,因此编制者需要发出诊断。
如果您将模板更改为:
template<typename T>
void foo(T t, T bar) {
t.compiler_does_not_care();
bar.nonexistent_method();
}
不涉及非依赖名称,因此不会发出错误,因为模板从未实例化(查找的第2阶段)
备注:强>
1)模板定义时间:最初解析模板时,在实例化之前,编译器会解析模板和 查找任何&#34;非依赖&#34;名。名字是&#34;非依赖&#34;如果 名称查找的结果不依赖于任何模板参数,和 因此,从一个模板实例化到另一个模板实例化将是相同的。
2)模板实例化时间:当模板被实例化时,编译器会查找任何依赖的&#34;名字,现在已经满了 用于执行查找的模板参数集。结果如此 查找可以(通常也是!)从一个模板实例化到 另一个。