仅标头模板(extern template)的显式实例化声明

Explicit instantiation declaration of header only template(extern template)

提问人:hidayat 提问时间:1/26/2017 最后编辑:Jan Schultkehidayat 更新时间:10/1/2023 访问量:585

问:

我正在尝试加快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>;

然后我有三个文件正在使用模板,是 的 typedef。这三个文件看起来几乎相同:glm::vec3glm::vec3glm::tvec3<float, glm::highp>a,b,c

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

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

C++ C++11 模板 Extern 显式实例化

评论

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

答:

-1赞 CHKingsley 11/30/2017 #1

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

这是留给学生的示例,但您想要如下内容:

math.h
结构 vec3{ double x1,x2,x3};
VEC3 Plus(康斯特VEC3&A,康斯特VEC3&B);

然后,当 a.cpp 包含 math.h 时,它提供了您需要的函数,但不会使所有编译单元都包含 glm.hpp。

评论

0赞 Jan Schultke 9/30/2023
即使包含标头,您仍然可以避免使用显式实例化的编译时间。标头只需要您解析其中的模板,而不是实例化它们。