显然模板库只需要是标题,但对于非模板,什么时候应该只使用标题?
答案 0 :(得分:14)
如果您认为您的非模板库可能只是标题,请考虑将其分为两个文件,然后提供包含.h
和.cpp
的第三个文件(包含后卫)。
然后,任何在很多不同的TU中使用你的库,并怀疑这可能花费大量编译时间的人都可以轻松地进行更改以测试它。
一旦您知道用户可以选择使用该库的方式,答案可能会变成“随时提供该选项”。因此,几乎任何时候从多个TU中包含它都不会违反ODR。例如,如果你的非static
自由函数引用static
全局变量,那么你就不走运了,因为不同TU中该函数的不同定义会用同一个名称引用不同的对象,这是违反ODR的行为。
答案 1 :(得分:3)
你可以关注Boost.Asio领导。
他们只提供两个版本的库:header-only和header + library。
他们在包含标题之前使用单个宏来定义(或不定义)。我认为默认(如果没有定义)是使用仅标题版本。
请参阅Optional Separate Compilation。
请注意它们如何整齐地提供要编译的单个源文件,用于定义所有内容或链接动态加载库的选项。
答案 2 :(得分:0)
模板库不需要只是标题:实现可能包含一些独立于模板参数的部分,并且由于某些原因(例如,代码大小较小)被分成特殊的二进制文件。
我无法想象一个非模板库真的必须只是标题的情况。但是,有时允许内联所有代码在性能方面可能是合理的。一个示例可以是围绕特定于平台的接口的包装器库,例如,用于诸如同步原语,线程局部存储,原子操作的平台和编译器特定实现等。
答案 3 :(得分:-2)
如果没有模板,您可以在标题中找到实际的定义。这意味着如果两个文件包含您的标题,您将获得多个定义,并且代码将无法编译。
换句话说,将标题放在标题中是一个非常糟糕的主意。你应该只使用声明和模板。
对于模板,编译器知道您可能会多次包含相同的标头,它们不会一遍又一遍地生成相同的代码。
编辑:如果你的意思是“保持一切内联”,我认为这是一个非常糟糕的方法。头文件变得完全不可读,并且实现中的任何更改都会强制库中的任何用户重新编译所有内容。