仅限标头的库设计 - 包含指令

时间:2014-05-20 16:41:49

标签: c++ c++11 include header-only

我正在创建一个仅限标头的C ++ 11/14库,我不确定如何处理库文件之间的#include指令。

我应该尝试在面向用户的模块头文件中尽可能多地组合#include指令,还是内部文件包含他们需要的文件(有时会重复相同的包含)?


方法A:

在此方法中,模块头文件包含所有必需的依赖项,然后包括实现。实现的头文件本身不包含任何内容。

// Library/Module/Module.hpp
// This file is intended to be included by the user in his projects.

#ifndef MODULE
#define MODULE

#include <vector>
#include "Library/Module/Impl/SharedDependency.hpp"
#include "Library/Module/Impl/Class1.hpp"
#include "Library/Module/Impl/Class2.hpp"

#endif MODULE

-

// Library/Module/Impl/SharedDependency.hpp

#ifndef SHARED_DEPENDENCY
#define SHARED_DEPENDENCY

inline void sharedFunc() { }

#endif

-

// Library/Module/Impl/Class1.hpp

#ifndef CLASS1
#define CLASS1

// No need to include "SharedDependency.hpp", as it will be included by
// the module header file. Same applies for <vector>.
struct Class1 
{ 
    std::vector<int> v;        
    Class1() { sharedFunc(); } 
};

#endif

-

// Library/Module/Impl/Class2.hpp

#ifndef CLASS2
#define CLASS2

// No need to include "SharedDependency.hpp", as it will be included by
// the module header file. Same applies for <vector>.
struct Class2
{ 
    std::vector<int> v;        
    Class2() { sharedFunc(); } 
};

#endif


方法B:

在此方法中,模块头文件仅包含实现头。如果实现头部需要额外的包含,则它们包括文件本身(递归地),有时重复相同的包含。

// Library/Module/Module.hpp
// This file is intended to be included by the user in his projects.

#ifndef MODULE
#define MODULE

#include "Library/Module/Impl/Class1.hpp"
#include "Library/Module/Impl/Class2.hpp"

#endif MODULE

-

// Library/Module/Impl/SharedDependency.hpp

#ifndef SHARED_DEPENDENCY
#define SHARED_DEPENDENCY

inline void sharedFunc() { }

#endif

-

// Library/Module/Impl/Class1.hpp

#ifndef CLASS1
#define CLASS1

#include <vector>
#include "Library/Module/Impl/SharedDependency.hpp"

struct Class1
{ 
    std::vector<int> v;        
    Class1() { sharedFunc(); } 
};

#endif

-

// Library/Module/Impl/Class2.hpp

#ifndef CLASS2
#define CLASS2

#include <vector>
#include "Library/Module/Impl/SharedDependency.hpp"

struct Class2
{ 
    std::vector<int> v;        
    Class2() { sharedFunc(); } 
};

#endif

什么是最好的方法?

直观地说,我认为方法A 是最好的,因为它避免重复相同的包含并清楚说明在其他文件之前需要包含哪些文件。但最大的缺点是,在没有包含指令的实现文件中,语法突出显示在我的IDE( QT-Creator )中停止工作。


编辑:

这个问题因“基于意见的”而被投票结束。我不同意,因为在一个大的头文件项目,如我的库包括文件可能需要大量的编译时间。因此,方法A可能比方法B更快,或相反。

1 个答案:

答案 0 :(得分:0)

方法B 实际上是最好的方法,因为多次包含相同的标题不会产生任何可观察到的编译时间增加,但是由于以下原因是有利的:

  • 现代IDE可以使用libclang或专有解决方案来解析#include指令,并提供代码感知语法突出显示和自动完成功能。

  • 正如TemplateRex所提到的,验证理智的构建过程变得更加容易。例如,CMake提供了自动为每个头生成测试的宏。

  • 正如Alf所提到的,优良作法是让每个文件都包含它所依赖的所有标题 - 然后图书馆的用户可以&#34;樱桃挑选&#34;他们需要的头文件,而不是意外强制手动包含父头。