什么时候实例化类模板?
Posted
技术标签:
【中文标题】什么时候实例化类模板?【英文标题】:When are class templates instantiated? 【发布时间】:2013-01-07 10:16:25 【问题描述】:假设您有以下(格式错误的)程序:
struct A
A(int, int)
;
template <typename T>
class B
B()
if (sizeof (T) == 1)
throw A(0); // wrong, A() needs two arguments
;
int main()
return 0;
GCC 编译这个程序没有任何错误,clang++ 错误拒绝它。
-
是否有理由说它是不是 GCC 中的一个错误,因为模板没有被实例化?
clang 有什么魔力可以找到这个错误?
C++ 标准对这些情况有何规定?
【问题讨论】:
另见***.com/questions/7182359/…。这两个关键字是“实例化点”、“两阶段查找”和“(非)依赖名称”。等等,那是三个关键词。 哦,废话,我想撤销我的近距离投票但不能。这对我来说很愚蠢。 没问题,感谢您的链接。 【参考方案1】:模板在使用时被实例化。但是,它应该在定义时进行编译。你的代码A(0)
使用了名称A
,它不依赖于模板参数T
,所以应该在定义模板的时候解决。这称为两阶段查找。 clang 发现错误的方法很简单,就是在看到调用 A(0)
后立即解决它。
我的 GCC 版本也会静默编译这段代码,即使是 -pedantic-errors
。 C++03 和 C++11 都说不需要诊断,即使程序格式错误,所以 GCC 符合。这是 C++03 中的 14.6/7 和 C++11 中的 14.6/8:
如果无法为模板定义生成有效的特化, 并且该模板未实例化,模板定义为 格式不正确,无需诊断。
【讨论】:
啊,我明白了。当我将 A 更改为模板类并调整对A<T>(0)
的调用时,clang 会编译它。也感谢两阶段查找的提示。你有什么有趣的建议吗?
格式不正确,但明确提到不需要诊断。
@AProgrammer:是的,更新了。我没有意识到 C++11 已经添加了这一点。
@Steve,在 C++03 (14.6/7) 中已经是这种情况,如果我没有误解 C++98 中的更改标记。 (C++03 中的其他语言使其“格式错误,无需诊断”,以便在实例化点完成不完整的类型。)。
@AProgrammer:哎呀,我看错了 C++03 中的段落,它们被重新编号了。【参考方案2】:
是的。当不存在有效的特化但没有实例化模板时——就像这里一样——程序格式错误,但不需要诊断 (14.6/8)。所以clang和g++都是对的。
clang 对模板声明的检查比 g++ 多。
见上文。
【讨论】:
当我们使用未声明/未定义的名称而不是A
时,行为有何不同?当名称未声明时(但未定义时不会),GCC 会抱怨(除非我们指定 -fpermissive
),但标准是否涵盖了这一点,或者这仍然是不需要需要诊断的情况?
@Konrad:文本是“如果无法为模板定义生成有效的特化,并且该模板未实例化,则模板定义格式错误,无需诊断。”。在这种情况下,修改代码以使代码包含一个完全未定义的名称,不能生成 B
的特化。以上是关于什么时候实例化类模板?的主要内容,如果未能解决你的问题,请参考以下文章