【问题标题】:Reduce sizes of template headers减小模板标题的大小
【发布时间】:2016-05-05 03:31:42
【问题描述】:

我正在开发一个大量使用模板的 C++ 库。对于大多数类,所有代码都驻留在某个.hpp 文件中,该文件将由客户端代码直接为#included。我担心两件事:

  1. 是否有一些设计模式可以将实现代码移至“后台”?当我设计非模板类时,我经常将“接口”类和实现类分开,前者会通过getImpl()->foo()之类的方式委托给后者,从而实现代码可以动态链接。我不确定如何为模板执行此操作。 我认为动态链接可能对模板没有意义?

  2. 大模板标题(> 1000 行)是否常见?或者这很糟糕?如果它不好,我该怎么办?

我知道这个问题How to reduce output size of template-heavy C++ code?,但我认为我们在问不同的事情:该问题的 OP 正在尝试减小 输出 的大小,而我正在尝试减小我的库头本身的大小。

更新:例如,如果您要设计std::vector,您将如何组织其接口和实现(如果需要)?

【问题讨论】:

  • 缩小尺寸到底是什么意思?为了避免因应用的模板参数种类过多而导致代码实例膨胀?
  • @πάνταῥεῖ 我主要指的是代码行数。向客户端公开千行标题对我来说是个坏主意(至少对于非模板代码而言)。
  • 如果您有不依赖于模板参数的非模板代码,请将其移出到单独的编译单元。
  • @πάνταῥεῖ 如果我的库代码是纯模板的,我假设您所说的仅适用于非模板 client 代码?
  • “我假设你所说的仅适用于非模板客户端代码?”当然。

标签: c++ templates


【解决方案1】:

不要太担心标题的大小。模板几乎总是将所有代码都放在一个标头中,因为每个客户端都必须知道如何实例化类,以防他们创建一个全新的版本(使用不同的模板参数)。

如果您担心 1000 行,请查看矢量。在 Visual Studio 2013 中,它是 3000 行。

话虽如此,您实际上只需要声明随处可用的类并定义一次,就像任何普通类一样。因此,可以有一个没有实现的模板头,然后创建一个带有实现的 .cpp。这个 .cpp 必须强制生成所有你需要的所有模板化类型。

在下面的示例中,B.cpp 的作者必须知道所有将要使用的模板参数。你不需要这么多文件,但我认为这应该涵盖所有场景。

B.h:

template<class T>
struct B
{
    B();
};

B_impl.h:

#include "B.h"
template<class T>
B<T>::B() {}

B.cpp:

#include "B_impl.h"
template struct B<int>;
template struct B<short>;

main.cpp:

#include "B.h"
B<int> b; 

【讨论】:

  • 所以可以有一个没有实现的模板头,然后创建一个带有实现的.cpp。这个 .cpp 必须强制生成所有你需要的模板类型。 这是用于客户端代码还是库代码?
  • 我用完整的代码示例编辑了答案(我用模板替换了 typedef,因为 typedef 不实例化模板类)。对库代码执行此操作非常危险,因为您可能不知道客户将使用您的库的每种类型。如果您要发布已编译的二进制文件,则您的二进制文件也必须包含所有实例化。想象一个你不能使用自己的类型的 std::vector。
  • 您可以将 B.h 和 B_impl.h 放入库中以避免这些问题,但我从未见过这样做过。此外,假设 B 类有 20 个函数,而 main.cpp 只使用其中一个。我认为编译器只需要编译 1 函数。但是,如果您使用上述模板 struct B,编译器必须编译所有 20 个函数(可能链接器会删除其中的 19 个)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-16
  • 1970-01-01
  • 2013-10-18
相关资源
最近更新 更多