是否永远不可能编写仅限标题的库?

时间:2010-09-20 17:13:12

标签: c++ header-only

是否存在这样的依赖模式,以至于不可能只保留头文件中的所有内容?如果我们仅对每个标题强制执行一个类的规则会怎么样?

出于这个问题的目的,让我们忽略静态事物:)

4 个答案:

答案 0 :(得分:7)

我知道标准C ++中没有任何功能,除了你已经提到的静态,它需要一个库来定义一个完整的翻译单元(而不是只有标题)。但是,建议不要这样做,因为当您这样做时,您会强制所有客户端在库更改时重新编译整个代码库。如果您正在使用源文件或静态库或动态库形式的分发,则可以更改/更新/修改您的库,而无需强制每个人重新编译。

答案 1 :(得分:5)

我会说,有可能在不使用多种语言功能的明确条件下:正如您所注意到的那样,对static关键字进行了一些使用。

可能需要一些技巧,但可以对其进行审核。

  1. 您需要在需要中断依赖关系周期时保持标头/源的区别,即使这两个文件在实践中都是头文件。
  2. 自由函数(非模板)必须内联声明,编译器可能不会内联它们,但如果它们被声明,那么当客户端构建其库/可执行文件时,它们不会抱怨它们已被重新定义。 / LI>
  3. 应使用函数/类方法中的本地静态属性模拟全局共享数据(全局变量和类静态属性)。在实践中,就调用者而言,它几乎没有意义(只需添加())。请注意,在C ++ 0x中,这成为一种受欢迎的方式,因为它保证是线程安全的,同时仍然保护初始化顺序惨败,直到那时......它不是线程安全的;)
  4. 尊重这三点,我相信你能够写一个完全成熟的仅限头文库(任何人都能看到我错过的其他东西吗?)

    许多Boost Libraries使用类似的技巧只是标题,即使他们的代码不是完全模板。例如Asio非常有意识地使用标志提出替代方案(参见release notes for Asio 1.4.6):

    • 只需要一些功能的客户无需担心构建/链接,只需抓住他们需要的内容
    • 依赖它的客户或希望减少编译时间的客户能够构建自己的Asio库(使用自己的标志集),然后包含“轻量级”标题

    这种方式(以图书馆开发人员的一些努力为代价),客户得到了他们的蛋糕,也吃了它。我认为这是一个非常好的解决方案。

    注意:我想知道static函数是否可以内联,我更喜欢自己使用匿名命名空间,所以从来没有真正研究过它......

答案 2 :(得分:2)

每个标题规则的一个类是没有意义的。如果这不起作用:

#include <header1>
#include <header2>

然后会有一些变化:

#include <header1a>
#include <header2>
#include <header1b>

这可能导致每个标头少于一个类,但是你总是可以使用(void *)和强制转换和内联函数(在这种情况下,编译器可能会正确地忽略'inline')。因此,在我看来,这个问题可以简化为:

class A
{
// ...
void *pimpl;
}

私有实现pimpl是否有可能依赖于A的声明?如果是这样,则pimpl.cpp(作为标题)必须在A.h之前和之后。但是,由于您可以再次使用前面标题中的(void *)和强制转换以及内联函数,因此可以完成。

当然,我可能是错的。在任何一种情况下:Ick。

答案 3 :(得分:1)

在我漫长的职业生涯中,我还没有遇到依赖模式,这种模式会禁止仅限标题的实现。

请注意,如果类之间存在循环依赖关系,则可能需要求助于抽象接口 - 具体实现范例,或使用模板(使用模板允许您转发引用模板参数的属性/方法,这些都是已解决的稍后在实例化期间)。

这并不意味着您应该始终瞄准仅限标头的库。它们很好,它们应该保留给模板和内联代码。它们不应包含大量复杂的计算。