以下 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 的代码的语义正确性(如果可以的话),即使它从未被实例化?这个标准符合吗?
Bar
是一个非依赖名称(即它的类型不依赖于T
),因此编译器需要在名称查找的第一阶段验证代码的正确性(参见下面的注释)。
Since Bar
has no nonexistent_method()
方法,编译器需要发出诊断。
如果您将模板更改为:
template<typename T>
void foo(T t, T bar) {
t.compiler_does_not_care();
bar.nonexistent_method();
}
不涉及非依赖名称,因此不会发出错误,因为模板从未实例化(查找的第 2 阶段)
Notes:
- 两阶段名称查找的可理解描述LLVM http://blog.llvm.org/2009/12/dreaded-two-phase-name-lookup.html :
1)模板定义时间:当模板最初被解析时,早在实例化之前,编译器就解析了模板和
查找任何“非依赖”名称。如果名称是“非依赖的”
名称查找的结果不依赖于任何模板参数,并且
因此,从一个模板实例化到另一个模板实例化将是相同的。
2) 模板实例化时间:当模板被实例化时,编译器会查找任何“依赖”名称,因为它具有完整的名称
用于执行查找的模板参数集。这样做的结果
查找可以(并且经常如此!)从一个模板实例到
其他。
- 至于why非依赖名称查找不能推迟到第二阶段,请参阅这另一个帖子 https://stackoverflow.com/questions/12561544/two-phase-name-lookup-for-c-templates-why;看来这主要是出于历史原因。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)