Header Only Library
什么是Header Only Library
Header Only Library把一个库的内容完全写在头文件中,不带任何cpp文件. 这是一个巧合,决不是C++的原始设计.
第一次这么做估计是STL.在80年代末C++编译器还不支持模块分离(现在也不支持,以后估计也不会支持了), STL的作者不得不把模板的实现写在头文件中, 使得一个STL库的实现绝大部分都展示给了使用者.
第一次广泛被接受估计还是在Boost库,它不只提出使用hpp做为Header Only Library的文件后缀(因为这些头文件再也不能用于C语言了),还把一些原本不是Header Only的库变成了Header Only.
抛开一些外部约束不谈,Header Only Library有自己的优点:Header Only Library - Wikipedia benefits of header only libraries - stackoverflow
1.轻量级编译流程,集成编译非常简单,只需要指明所在路径,在C++实现文件中包含所需头文件即可.
2.编译器优化可以做得更好.因为内联函数和所有的实现都在编译时可见,所以可以进行相当多的优化,包括一些全局优化.
3.更好的代码设计.因为不能使用写全局变量和静态变量,以及所有的代码都公开可见,使得很多不良设计都无处藏身.
4.减少了ABI接口变更的风险.部分编译选项会导致静态库/动态库的ABI变化或者行为变化,库的作者需要提供多个版本的库文件, 包括但不限于32/64bit, 静态/动态库, struct layout等不同组合.
Header Only规避了这个问题.
当然它的缺点也很明显.
1.变更会导致全部组件重新编译.这就要求Header Only Library尽量应为相对稳定的功能库,而不是做为接口库.
2.代码组织不合理时,编译时间会显著变长.大量使用Header Only Library需要合量划分编译单元,减少编译单元的数量
可以有效提高编译速度.就我的实践来看每个编译单元应大于1万行(不包括头文件).boost separated source
Header Only Library常被误解会导致编译后代码变大. 因为Header Only Library大量使用模板技术, 以增加灵活性,
模板是会一定程度上增加编译结果的大小. 排除这一点, Header Only Library不会导致编译后代码明显变大.原因主
要是编译器的优化起作用.Benchmards - Stackoverflow
- 大量的内联会增加代码编译的结果.
- 按需实例化会减少不用的代码链接到代码中.
- 死代码发现机制,会减少一部分不使用的代码.
如何创建Header Only Library
首先应选一个名字空间,比如 work4me,建议使用全小写,最好与web domain相同. 头文件中所有类,常量,函数,模板,枚举以及联合
都应在这个名字空间之内声明. 头文件也应放在同名目录之内, 且使用hpp做为后缀.
头文件中除了命名空间以外,只能包括:
- 类/枚举/联合的声明和定义
- 常量/常量表达式的声明和定义
- 类模板,函数模板定义
- typedef和using产生的名字.
- 内联函数和内联成员函数的定义
建议提供一个fwd.hpp来放置所有模板的前置声明, 以及一些函数和函数模板的前置声明. 因为如果在模板声明中用到默认参数,用户就没有
办法写自己的模板前置声明.(默认模板参数只能在第一次声明时指定,且只能指定一次,那怕各处都保持一致也会编译失败).
特别需要注意所有函数定义,都需要加上inline关键字.
不能使用static定义任何全局的变量和函数.不能定义类的static变量成员,但可以定义内联的static成员函数.
不能使用匿名命名空间.如果需要向用户隐藏一些接口或类型,可以使用details/impl等表示实现的嵌套命名空间.
如果依赖标准库以外的第三方库,应在ReadMe中做出说明.
如果依赖平台库比如windows.h/pthread.h等平台专有库,可以考虑bridge模式把这实现部分放到win32,linux等嵌套命名空间下.
什么时候适用
Header Only Library适合通用类库,因为需求变动不大,对灵活性和效率要求较高.包括boost内这些语言工具,基础算法,基础工具.
不适合功能性比较强,需要减少耦合的地方.比如一些正交的功能模块.
做为折中,可以把功能模块本身写成Header Only Library,但使用一个编译单元把它与其它部分隔离.常用的隔离技术比如PIMPL可以在这里使用.
Header Only Library的更多相关文章
- 【转】Header Only Library的介绍
什么是Header Only Library Header Only Library把一个库的内容完全写在头文件中,不带任何cpp文件. 这是一个巧合,决不是C++的原始设计. 第一次这么做估计是ST ...
- Please ensure the argon2 header and library are installed
在CentOS上安装libargon2和libargon2-devel即可 yum install -y libargon2 libargon2-devel
- How to build the Robotics Library from source code on Windows
The Robotics Library is an open source C++ library for robot kinematics, motion planning and control ...
- c++中的header-only library
不同于在java中,虽然在java中,有些第三方库只是做了桥接的功能,比如slf4j-log4j-api,但是在运行时他们仍然是需要的,所以最多只能说是松耦合做得很好. 但是在c++中,一般我们应用第 ...
- Google C++ Style Guide
Background C++ is one of the main development languages used by many of Google's open-source project ...
- 关于c++风格 code style
Header files should be self-contained. All header files should have #define guards to prevent multip ...
- 安装coreseek找不到mysql
1.安装 coreseek-3.2.14 遇到问题:“ERROR: cannot find MySQL include files,随即在网上搜索各种答案说是要找到mysql.h的正确路径加入./co ...
- 升级openssl
升级openssl 依赖openssl的软件,如果是静态编译openssl,那么需要重新编译软件,如果是利用openssl的so动态库,那么只需要替换一下so文件并重启软件即可 openssh也依赖o ...
- mysql 升级方法
Performing an In-place Upgrade This section describes how to perform an in-place upgrade. Review Bef ...
随机推荐
- Linux 配置静态Ip地址
注:所有红色字体标注均为 Linux 的 操作命令 ! 1, 使用root账户登录系统 2, 可以先使用 ifconfig : 查看网卡信息 eth0 为默认的第一个网卡 , 如果有第二个就会显示 ...
- sqlserver卸载
- H5浏览器播放RTMP直播流
<!DOCTYPE html><html><head><meta charset="UTF-8"><title>Inse ...
- js操作一般文件和csv文件
js操作一般文件和csv文件 将文本文件读成字符串 <input type="file" id="upload"> document.getElem ...
- seureCRT快捷键
前言 secureCRT 是一个非常不错的终端软件,在嵌入式开发过程中经常使用到,所以了解一下其快捷键操作是非常有必要的,可以提高开发效率. 复制:[ctrl] + [shift] + c 粘贴 ...
- 十分钟学会Fiddler
一.Fiddler介绍 Fiddler是一个http抓包改包工具,fiddle英文中有“欺骗.伪造”之意,与wireshark相比它更轻量级,上手简单,因为只能抓http和https数据包,所以在针对 ...
- openark对MySQL进行Online_DDL
1.用oak对表sbtest1做添加字段和增加索引的Online DDL openark kit 提供一组小程序,用来帮助日常的 MySQL 维护任务,可代替繁杂的手工操作. 包括: oak-appl ...
- C# XML文件操作
C# XML文件操作 运行环境:Window7 64bit,.NetFramework4.61,C# 6.0: 编者:乌龙哈里 2017-02-09 参考 LINQ to XML System.Xml ...
- Django的admin使用
现在假设我们自己定义了一个用户模型和成员模型,我们需要在Django后台对它进行管理,使用admin可以对模型进行相关的展示设置和管理. from django.contrib import admi ...
- grep家族
grep家族由命令grep.egrep和fgrep组成. grep:在文件中全局查找指定的正则表达式,并且打印所有包含该表达式的行.egrep和fgrep是grep的变体.egrep:grep的扩展, ...