仅标头模板的显式实例化声明(外部模板)

Posted

技术标签:

【中文标题】仅标头模板的显式实例化声明(外部模板)【英文标题】:Explicit instantiation declaration of header only template(extern template) 【发布时间】:2017-06-11 21:00:31 【问题描述】:

我正在尝试加快 GLM(OpenGL 数学)的编译时间。 GLM 大量使用 C++ 模板。

这是我迄今为止尝试过的。

math.h
#pragma once

#include <glm\glm.hpp>
extern template struct glm::tvec3<float, glm::highp>;

math.cpp
#include "math.h"
template struct glm::tvec3<float, glm::highp>;

然后我有三个使用glm::vec3 模板的文件,glm::vec3glm::tvec3&lt;float, glm::highp&gt; 的类型定义。 a,b,c 的三个文件看起来几乎一样:

a.cpp, b.cpp, c.cpp
#include "math.h"
glm::vec3 func() 
    glm::vec3 a = glm::vec31,1,1;
    glm::vec3 b = glm::vec31,1,1;
    return a + b;

我同时使用显式实例化定义和显式实例化声明。所以文件a,b,c 不应该导致隐式实例化。 但是编译时间和我不做一样。

【问题讨论】:

AFAIK,如果您将模板声明移动到单独的 .cpp 文件中并仅显式实例化所需的模板,显式实例化只能帮助加快编译时间。仅标头库并非如此。更糟糕的是:显式实例化类将生成其所有符号,包括未使用的符号 @AndreiR。您不必隐藏模板实现以避免隐式实例化,从而强制编译器在其他翻译单元中搜索它。这就是extern template 的全部意义 -> 强制编译器在其他翻译单元中搜索实现,而不是在当前翻译单元中实例化它。 @PcAF 但是这个例子应该可以工作,不是吗? 我猜即使@PcAF 是正确的,这里的问题是编译器仍然必须解析整个头文件。由于在您的示例中您只使用(可能很简单)构造函数,因此编译它不会节省太多时间。 这个问题引起了我的注意,我没有答案,但其他用户在尝试将外部模板与 glm 一起使用时报告了您同样的问题:cpc110.blogspot.com/2020/04/… [来自该页面:“我怀疑这是因为 #include 实际上最终确实包含了模板定义,而在这一点上,后续的 extern 模板声明只是多余的。"] 【参考方案1】:

您的 math.h 仍然会导致用户包含 这就是你想要避免的事情,以加快速度。为了加快速度,创建您自己的类,其实现(在 math.cpp 中)可能使用 glm.hpp,但该类的用户不需要自己包含 glm.hpp。

这是留给学生的示例,但您需要类似:

数学.h 结构 vec3 双 x1,x2,x3; vec3 plus(const vec3& a, const vec3& b);

那么当a.cpp包含math.h时,它提供了你需要的功能,但不会让你所有的编译单元都包含glm.hpp。

【讨论】:

以上是关于仅标头模板的显式实例化声明(外部模板)的主要内容,如果未能解决你的问题,请参考以下文章

用于实例化模板代码的显式习惯用法 - 不包括其源代码

正确使用函数的显式模板实例化?

gcc中的模板显式实例化(定义和声明)

MSVC:显式模板实例化失败,而隐式实例化成功

使用模板化成员函数显式实例化模板类

将 pimpl 与 Templated Class 和显式实例化的模板一起使用