什么时候实例化类模板?

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&lt;T&gt;(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 的特化。

以上是关于什么时候实例化类模板?的主要内容,如果未能解决你的问题,请参考以下文章

实例化类的时候代码运行顺序

实例化类对象是啥意思?

实例化类的 Python3 问题

在pyqt中使用yaml 实例化类

在pyqt中使用yaml 实例化类

Delphi 通过字符串实例化类