仅头文件库设计-包含指令
Header-only library design - include directives
我正在创建一个仅头文件的c++ 11/14库,我不确定我应该如何处理库文件之间的#include
指令。
我应该尝试在面向用户的模块头文件中尽可能多地分组#include
指令,还是应该内部文件包括他们需要的文件(有时重复相同的包括)?
方法:
在这种方法中,模块头文件包括所有必需的依赖项,然后包括实现。实现头文件本身不包含任何内容。
// 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:
在这种方法中,模块头文件只包含实现头文件。如果实现头文件需要额外的include,它们会包含文件本身(递归地),有时会重复相同的include。
// 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)中停止工作,在没有include指令的实现文件中。
编辑:
由于"基于意见"的原因,该问题被投票关闭。我不同意,因为在像我的库这样的大型头文件项目中,包含文件可能会花费大量的编译时间。因此,方法A可能比方法B快,或者相反。
方法B实际上是最好的方法,因为多次包含相同的头文件不会产生任何可观察到的编译时间增加,但有以下优点:
-
现代ide可以使用
libclang
或专有解决方案来解析#include
指令,并提供代码感知的语法高亮和自动完成功能。 -
正如TemplateRex所提到的,验证一个相同的构建过程变得更加容易。例如,CMake提供了为每个头自动生成测试的宏。
-
正如Alf所提到的,让每个文件包含它所依赖的所有头文件是一种良好的做法-库的用户可以然后"挑选"他们需要的头文件,而不是意外地强制手动包含父头文件。
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- cmake如何在fedora工作站中找到boost静态库包
- 无法编译 rtmidi 测试 cmidiin.cpp 文件, 非法指令
- 如何将enable-if与模板参数和参数包一起使用
- C++:对不存在的命名空间使用命名空间指令
- 在没有Xcode的情况下在Mac捆绑包中嵌入框架
- 为什么这个音频包络不能通过开关的情况?
- 函数名是c中该函数的第一条指令的地址吗
- 模板元编程:如何将参数包组合成新的参数包
- 如何将C++闭包与变量参数同时重用——类似于JavaScript
- 错误:无效的预处理指令 #i 的意思是 #if?
- AcquireCredentialsHandleA() 返回 PFX 文件的0x8009030e(安全包中没有可用的凭据
- C ++:在构造函数中使用参数包?
- struct.error:解压缩 C++ 结构时,解包需要 288 字节的缓冲区
- 组装指令中乘法的下部和上部是什么
- MSYS2 MinGW程序包中缺少grpc_cpp_plugin协议
- 如何使我的 sizeof sum 结构与空参数包一起工作
- boost::asio UDP 广播客户端仅接收"fast"数据包
- SSE/SSE2 指令的打包和解包数据