【问题标题】:How would export templates be implemented?导出模板将如何实现?
【发布时间】:2017-06-29 04:48:36
【问题描述】:

导出模板是 2011 年之前的 C++ 中的一项功能,其中模板的实现将推迟到单独的源文件。

According to this article,可以通过手动指定实现文件中使用的每种类型来编写“手动”导出模板。由于这只会创建特定的符号 - 我相信与重载函数类似的方式 - 这将如何实现是有意义的。

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

举个简单的例子:

template<typename T>
T add(T value1, T value2) {
    return value1 + value2;
}

如果 T 是 intfloat 或特别是 std::string(以及任何其他重载 + 运算符的类型),则此示例的程序集输出会大不相同。

既然完全是任意的,编译器将如何实现这个关键字?

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

【问题讨论】:

    标签: c++ templates compiler-construction c++98


    【解决方案1】:

    大约在 2001 年,EDG 实现了export,Comeau 为我提供了早期构建。我确实能够实例化A&lt;B&lt;A&lt;B&lt;A&lt;int&gt; &gt; &gt; &gt; &gt;,其中A&lt;T&gt; 在A.cpp 中定义,B&lt;T&gt; 在B.cpp 中定义。显然,这需要某种形式的链接时代码生成。

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

    【讨论】:

      【解决方案2】:

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

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

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

        export templat< ... > class foo;
      

      它没有生成代码的机制,并且在请求 foo 类的特性时失败。

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

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

      如果您显式实例化模板的具体示例,则可以从库中导出这些示例,但仅限于预先知道的类型。

      【讨论】:

        【解决方案3】:

        有些人期望导出的模板是严格单独的编译器,但没有证据表明这些人(如果存在的话)是委员会成员。

        导出的模板确实是具有普通模板语义的普通模板。 (它们不是类似的 O'Caml 或 Haskell 模块。)

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

        C++ 中的模板本质上类似于宏。不是蹩脚的 C/C++ 预处理器宏,它们是基于标记的,因此忽略了 C 或 C++ 语法结构,但它们非常接近基于替换(在语法实体而不是词法分析器杠杆上)。

        他们倾向于从实例化上下文中提取很多的名称,比我们想要的要多。那是因为在 C++ 中没有办法拥有“概念”元类型系统。 (而且 C++ 太复杂,太不规则,无法改造这样的东西。)

        如果没有 C++ 模板的“概念”契约,C++ 语言定义就不能严格限制可能在实例化上下文中查找的名称:即使像 a&lt;b 这样显而易见的东西也不是布尔值C++ 中的值。按照惯例,它是由普通布尔类型(boolint)表示的布尔值,但它可以是任何东西(有将返回类型设为类类型的用例)。

        因此,即使模板中的 f(a&lt;b) 之类的内容也可能需要从实例化上下文中提取 f,这与 f(bool(a&lt;b)) 不同。

        显然不可能真正单独编译模板。这绝不是导出模板的意图。

        模板是基于模板定义上下文和实例化点上下文进行实例化的;如果模板不是头文件,那只是意味着编译器会考虑两个源文件。因此,它甚至不是一个严重的困难。 (当然有困难的问题,但处理多个源文件不是一个。)

        当然,这意味着 C++ 代码的“链接”不会是正常的链接:它将涉及为每个所需的模板实例化再次运行编译器,直到所有实例化完成。

        (并且“运行时链接”将不包括此类模板实例化链接,并且不允许调用编译器来创建代码。)

        我在这里提到的一切在当时都是清楚明了的。零证据表明,任何为语言设计做出重大贡献的人曾经有不同的直觉。

        其实原来C++只有导出模板,以至于没有export关键字

        【讨论】:

          猜你喜欢
          • 2021-07-26
          • 2021-08-02
          • 1970-01-01
          • 2012-02-16
          • 1970-01-01
          • 2023-04-01
          • 2021-09-10
          • 2020-08-05
          • 2019-11-09
          相关资源
          最近更新 更多