库设计混乱..“公共” /“私有”(模板)标题,库文件..

时间:2018-07-07 13:49:09

标签: c++ c++11 templates project header-files

我正在尝试编写我的第一个(非常)小的库,目前仅供自用。在此过程中,我遇到了有关如何以逻辑方式分隔标题/源代码/目标文件的问题。

更具体地说,我正在编写一个小型的模板化容器类,因此对于我来说,必须在其标头中包含该类的实现。

我有这样的目录结构:

include/ - "public" .hh header files included by extern projects
src/ - .cc files for implementation (+ "private" .hh header files?)
lib/ - .o compiled library files linked by extern projects

我还不确定这是否有意义..就我而言,我还编写了一些我的模板化容器类使用的帮助器类,其中一个类似于迭代器。所以我有以下文件:

container.hh
container.cc
container_helper.hh
container_helper.cc
container_iterator.cc
container_iterator.hh

虽然我想在外部项目中访问它们的功能(例如,增加迭代器),但对我来说,一个项目将特别有意义

#include "container_iterator.hh"

现在,由于我希望项目能够使用容器类,因此我将“ container.hh”和“ container.cc”(因为由于模板而必须包含在“ container.hh”中)放入了“ include /”目录,其他项目随后将其包括在内。 现在,我的困惑出现了。容器类需要访问帮助器类,但是我不希望其他项目仅包含帮助器类,因此将帮助器类也放置在“ include /”目录中似乎是错误的。相反,我会将它们放在“ src /”中。 但是,如果要这样做,那么要将它们包括在“ include / container.cc”中,我必须使用相对文件路径

#include "../src/container_iterator.hh"

但是现在,如果我将我的库“分发”到外部项目,即仅使“ include /”目录对编译器可见,则它将不会编译(?),因为“ ../src/container_iterator.hh “ 不存在。 还是我编译容器类并将其作为库放入“ lib /”中,然后由其他项目链接?但是即使那样,我仍然不需要包含标题“ container.hh”来查找函数声明,这会导致相同的问题吗?

基本上我在这里迷路了。.标准是怎么做到的?例如。我可以

#include <vector>

,但是我不知道任何标头只包含std :: vector :: iterator,这样做没有任何意义。

在我扩张的某个时刻,我一定在胡说八道,但是我找不到位置。我想我了解/应该是什么标题和库,但是当涉及到如何为实际项目设计和/或“分发”它们时,我会感到困惑。即使当我开始学习C ++(或与此有关的任何语言)时,我仍然遇到类似的问题,没有课程/没有书籍似乎解释如何实现所有这些概念,只有当它们已经存在时才如何使用它们。 / p>

编辑

更多地澄清我的困惑(?)(这太长了,无法发表评论),我之前确实读过将模板类的实现放入标头中,因此我意识到我至少需要将将“ container.cc”放入包含/目录。尽管我不是特别喜欢这种方式,但至少外部用户应该清楚地不包含“ .cc”文件。

我是否也将其理解为意味着将模板化的类编译到库中永远都没有意义,因为所有这些都将始终包含在内? (因此,模板化代码始终是开源的吗?..听起来是错吗?)

在这种情况下,我仍然想知道STL是如何做到的,vector是否在自己的标头中声明并定义了它的迭代器?还是我可以包含vector :: iterator的单独标头,这样做没有任何意义?


希望我已经清楚地解释了我的意图,如果没有,请发表评论。 感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

根据我的经验,最常见的处理问题的方法是在模板声明和文档(您的.hh文件)中包含标头,其中还包括.inc.tcc(您的偏好)文件以及模板定义。我还建议将外部项目可能包含的所有文件都放在同一文件夹中,但是如果您想保持整洁,请将.inc / .tcc文件放在include内的文件夹中称为detail(如果您喜欢GNU样式,则称为bits)。 将内容放入详细资料文件夹中,  并使用怪异的扩展名应该足以吸引用户。

要回答您的其他问题: 由于C ++模板的性质,  您使用的模板部分的全部来源  必须存在于翻译单元中(例如#include),  ,您可以使用explicit instantiation  对于有限数量的参数  (不过,这通常对容器没有用)。 因此,在大多数情况下,您必须分发模板的源,  当然,(如评论中所述)“开源”是关于许可证的,  没有来源可见性。

对于标准库,让我们以<vector>为例。 GNU C ++库具有一个vector文件,该文件除其他事项外还包括  bits/stl_vector.h包含声明和文档,  并包含具有定义的bits/vector.tcc。 LLVM的libc ++只有一个大文件,  但是将声明放在顶部(没有文档!)  底部的所有定义。

最后一点,将来有很多开源C ++库供您参考!