2011-05-28 53 views
24

显然,模板库只需要标题,但对于非模板,什么时候应该只做标题?什么时候应该考虑制作库标题?

+2

当你不介意暴露你的IP。 – Nim 2011-05-28 22:50:59

+0

@Nim:它是Boost软件许可下的开源程序,所以我当然不介意。 :) – 2011-05-28 22:55:09

+0

@比利:哦,你进入了Boost?格拉茨? :P – Xeo 2011-05-28 22:57:44

回答

14

如果您认为您的非模板库可能仅包含标题,请考虑将其分为两个文件,然后提供第三个包含.h.cpp(包含后卫)的文件。

然后,任何人在很多不同的TU中使用您的库,并怀疑这可能会花费大量编译时间,可以轻松地进行更改以对其进行测试。

一旦您知道用户可以选择使用该库的方式,答案可能会变成“只要可能就可以提供该选项”。几乎任何时候,包括来自多个TU的内容都不会违反ODR。例如,如果您的非空函数引用了全局变量,那么您就不幸运了,因为不同TU中该函数的不同定义会以相同的名称引用不同的对象,这是违反ODR的。

+2

Oooh。从来没有想过这样做。 +1当'.cpp'为'#include'd时,你如何正确地将函数声明设置为'inline'? – 2011-05-28 22:54:20

+2

@Billy:在第三个文件(第二个.h)中设置一个'#define',并在.cpp中设置#ifdef _____ #define DO_INLINE inline #else #define DO_INLINE#endif'。 – Xeo 2011-05-28 22:55:56

+1

或者只是将它们标记为'inline',它不会造成任何伤害。 – 2011-05-28 22:58:06

-2

如果没有模板,你会在头文件中有实际的定义。这意味着如果两个文件包含你的头文件,你会得到多个定义,并且代码不会被编译。

换句话说,将定义放在标题中是一个非常糟糕的主意。你应该坚持只声明和模板。

至于模板,编译器知道你可能会多次包含相同的头文件,它们不会一遍又一遍地生成相同的代码。

编辑:如果你的意思是“保持一切内联”,我认为这是一个非常糟糕的做法。头文件变得完全不可读,实现中的任何更改都会强制库的任何用户重新编译所有内容。

+0

-1:这是不正确的。只要内部链接,您可以将定义放在标题中。 (例如,它们被声明为“inline”) – 2011-05-28 22:56:05

+0

'inline'。 'nuff说。 – Xeo 2011-05-28 22:56:24

+0

有时,需要重新编译每一个变化并不是这样的限制。 – 2011-05-29 03:18:18

0

模板库不需要仅用于标题:实现可能包含一些独立于模板参数的部分,并且由于某些原因(例如较少的代码大小)被分离为特殊的二进制文件。

我无法想象一个非模板库真的必须是仅标题的情况。但是有时候,允许内联所有代码可能是合理的性能。一个例子可以是围绕特定于平台的接口的包装库,例如用于像同步原语,线程本地存储,原子操作的平台和编译器特定实现等。

+0

Alexey:向我展示一个不是** header的STL库。而对于STL,我的意思是容器/算法/迭代器部分,而不是整个标准库。 – Xeo 2011-05-28 23:04:27

+0

也许,但模板库的模板部分只能是标题。模板定义需要存在于翻译单元中,以便编译器可以实例化它。一些STL具有二进制部分,主要是因为A.它们被包含为一般C++运行时的一部分,该运行时具有非模板片段(例如'libstdcxx'),或者B.它们包含不是模板的组件。至于性能方面,大多数编译器现在都有链接时间代码生成,这几乎消除了发布版本之间的性能差异。 – 2011-05-28 23:04:49

+0

@Xeo:好的,你可能是正确的,STL和语言支持库不一样。 – 2011-05-28 23:09:05

3

您可以按照Boost.Asio的指导。

他们只是提供了两个版本的库:header-only和header + library。

他们在包含头文件之前用一个宏定义(或不​​包含)。我认为默认(如果没有定义的话)是使用纯标题版本。

请参阅Optional Separate Compilation

注意它们是如何巧妙地提供一个单一的源文件来编译定义的一切或与动态加载库链接的选项。

相关问题