【问题标题】:When is it appropriate to explicitly instantiate templates?什么时候适合显式实例化模板?
【发布时间】:2014-07-28 23:25:03
【问题描述】:

在相关问题Why can templates only be implemented in the header file? 中,描述了避免链接器错误的两种策略:

  1. 在头文件中实现整个模板;或
  2. 使用template class Foo<int> 语法显式实例化模板。

据我所知,#1 似乎是“首选”方法,并且在每个库中都使用了 - 大概是因为很难或不可能预测库使用者想要使用哪些类型。我的问题涉及策略 #2。

具体来说,我为什么要这样做?

仅供参考:我大多是 C++ 新手,具有丰富的 C# 背景。我已经习惯了 .NET 风格的泛型,这更简单一些,是的,我理解 为什么 它们是不同的。但是,我假设 C++ 开发人员仍然关心耦合。表格 #2 是否不会引入一种特别烦人的耦合形式,开发人员必须不断编辑模板的 .cpp 文件,才能将模板用于不同的、以前无法预料的类型?这不是违背了模板的目的吗?

是否存在与解决方案 #2 相关的合法或重要用例?

【问题讨论】:

  • 是的,有一个明显的重要用例:在大多数桌面/服务器平台上链接的动态 C++ 库 (dll / so) 包含最常用模板的实例化,即使它们可能没有那里需要。 (尽管如此,尽管它们被声明为 extern 以避免非内联实例化,但它们仍然在头文件中完全定义)
  • @Deduplicator:你能解释一下为什么这是一个好处吗?我不是在质疑它,我只是不太明白,并且希望在答案形式中进行一些详细说明。
  • @Aaronaught 它加速了编译和链接,如果模板是预先实例化的,那么编译器就不必为每个目标文件创建单独的实例。在链接期间,链接器也不必解析多个实例化。

标签: c++ templates


【解决方案1】:

在header中实现整个模板有明显的优势(首选方法):

  • 添加模板特化:许多标准库模板可能是特化的。
  • 在新类型上使用它:模板是为了通用性,如果您不能随意选择模板参数,则会受到很大限制。
  • 学习其他模板专业化。

那么,为什么在实现文件中使用显式模板实例化,而只在头文件中提供模板的接口呢? (纯粹的方法根本没有真正使用)

  • 实现隐藏。
  • 编译速度更快!!由于大量使用模板,否则我们会遇到经典的O(n*m) 问题
  • 将这些模板放在共享库中以减少代码大小。

还有一种混合方法,它试图获得第二种方法的一些优点,同时保留第一种方法的所有优点:

使用extern 定义最常用的模板实例化,并提供来自共享库的显式实例化。

这具有第一种方法的所有优点,但与第二种方法相比只有一个优点:
这些显式实例化可以在共享库中。

共享 C++ 语言库使用这种混合方法。

顺便说一句:委员会对当前的事态并不满意:
他们正在开发一个真正的模块系统,该系统将结合两者的优点。
这篇 SO 帖子有一些信息:C++ Modules - why were they removed from C++0x? Will they be back later on?
2014 年 5 月的 C++ 委员会提案:A Module System for C++

【讨论】:

    【解决方案2】:

    当您想编写任何人都可以使用的通用类或函数时,请使用数字 1。当您想为多个特定类型重载一个类或函数时使用数字 2,但它们都将具有相同的实现。

    【讨论】:

    • 这在技术上显然是正确的,尽管它本质上是在说明实现的什么。但是为什么你会想要这样一个模板,一个仅限于特定类型的模板?
    • @Aaronaught template<bool optionA> void do_task();
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-16
    • 2021-11-25
    相关资源
    最近更新 更多