如何实现导出模板? 导出模板是2011年前C++中的一个特性,其中模板的实现将被推迟到单独的源文件。

如何实现导出模板? 导出模板是2011年前C++中的一个特性,其中模板的实现将被推迟到单独的源文件。,c++,templates,compiler-construction,c++98,C++,Templates,Compiler Construction,C++98,,可以通过手动指定实现文件中使用的每种类型来编写“手动”导出模板。由于这将简单地创建特定的符号——我相信这与重载函数的方式类似——因此如何实现这一点是有意义的 但据我所知,导出的模板(通过export关键字)是任意的。它可以允许传递任何类型的数据 举个简单的例子: template<typename T> T add(T value1, T value2) { return value1 + value2; } 模板 T添加(T值1,T值2){ 返回值1+2; } 如果T

,可以通过手动指定实现文件中使用的每种类型来编写“手动”导出模板。由于这将简单地创建特定的符号——我相信这与重载函数的方式类似——因此如何实现这一点是有意义的

但据我所知,导出的模板(通过
export
关键字)是任意的。它可以允许传递任何类型的数据

举个简单的例子:

template<typename T>
T add(T value1, T value2) {
    return value1 + value2;
}
模板
T添加(T值1,T值2){
返回值1+2;
}
如果T是
int
float
,或者特别是
std::string
(以及任何其他重载
+
运算符的类型),则此示例的程序集输出将大不相同

由于它是完全任意的,编译器如何实现这个关键字


我的猜测是在链接时生成代码,这很可能需要自定义对象文件格式,其中包含一些代码表示。但这也使得链接器成为一个编译器,这打破了预处理器-编译器-链接器的分离。

模板化的东西只有在被编译的代码引用时才被实例化为具体类型

此时,编译器需要所有信息(结构定义、函数定义)才能生成代码

如果编译器在导入结构时看到的唯一定义是

  export templat< ... > class foo;
导出模板<…>foo类;
它没有生成代码的机制,并且在请求类foo的特性时失败

相反,在构建库时,编译器可以使用定义和实现,但它看不到库可能使用哪些类型

唯一可用的(需要的?)机制是头文件。这具有定义和实现,并且避免了对特殊对象格式的需要


如果您显式地实例化了模板的具体示例,则可以从库中导出这些示例,但只能导出已知类型。

大约在2001年,EDG实现了导出,Comeau为我提供了早期构建。我确实能够实例化
A
,其中
A
在A.cpp中定义,而
B
在B.cpp中定义。显然,这需要某种形式的链路时间代码生成


这更令人惊讶,因为Comeau实际上使用MSVC作为后端,而微软同时认为这是不可能的!(这就是我首先评估导出的原因,WG21文件N1426)

有一个神话,一些人希望导出的模板严格独立于编译器,但没有证据表明这些人(如果他们存在的话)是委员会成员

导出的模板实际上是具有普通模板语义的普通模板。(它们与O'Caml或Haskell模块不同。)

产生二进制代码的单独编译是基于ABI的。为函数模板(与其实例化相反)创建ABI是没有意义的

<>强> C++中的模板基本上是类似于< /强>的宏。不是蹩脚的C/C++预处理器宏,它是基于令牌的,因此忽略C或C++语法结构,但是它们非常接近于替换(在语法实体而不是词素杠杆)。 他们倾向于从实例化上下文中提取大量的名称,比我们想要的更多。这是因为C++中没有“概念”元类型系统。(C++过于复杂,太不规则,无法修改这样的东西。) 没有C++模板的“概念”契约,C++语言定义不能严格限制在实例化上下文中查找的名称:甚至是明显的,如<代码>