什么是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

  1. 大量的内联会增加代码编译的结果.
  2. 按需实例化会减少不用的代码链接到代码中.
  3. 死代码发现机制,会减少一部分不使用的代码.

如何创建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可以在这里使用.

==============================================

本文转载于http://www.cnblogs.com/ahuangliang/p/cxx-practices-header-only-library.html

作者黄亮

【转】Header Only Library的介绍的更多相关文章

  1. Header Only Library

    什么是Header Only Library Header Only Library把一个库的内容完全写在头文件中,不带任何cpp文件. 这是一个巧合,决不是C++的原始设计. 第一次这么做估计是ST ...

  2. 【转】Android Support Library详细介绍

    网上对Android Support Library中各个依赖包介绍的中文资料太少了,结合官方文档和有限的参考资料做了一次总结,有描述得不对的地方还请指正. 一.主工程.依赖包.jar包.androi ...

  3. Android Support Library详细介绍

    网上对Android Support Library中各个依赖包介绍的中文资料太少了,结合官方文档和有限的参考资料做了一次总结,有描述得不对的地方还请指正. 一.主工程.依赖包.jar包.androi ...

  4. FGX Native library功能介绍

    Hot news from the fields of the cross-platform library "FGX Native" development. New Engli ...

  5. Please ensure the argon2 header and library are installed

    在CentOS上安装libargon2和libargon2-devel即可 yum install -y libargon2 libargon2-devel

  6. 文件下载及header方法介绍

    文件下载: 文件下载是浏览器一个功能,我们用php,把一个文件转化成浏览器无法解析的文件,浏览器就会认为,他是下载文件或无效文件. 主要依靠:header() 函数: header() 方法用于客户端 ...

  7. 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 ...

  8. Android应用Design Support Library完全使用实例

    阅读目录 2-1 综述 2-2 TextInputLayout控件 2-3 FloatingActionButton控件 2-4 Snackbar控件 2-5 TabLayout控件 2-6 Navi ...

  9. Android Design Support Library: 学习CoordinatorLayout

    简述 CoordinatorLayout字面意思是"协调器布局",它是Design Support Library中提供的一个超级帧布局,帮助我们实现Material Design ...

随机推荐

  1. [转]shell awk 入门,中级,高级使用

    awk很常用,对于我们在shell中分析log和file很有好处,很实用的东西,大家一起分享学习- 作为技术支持工程师,我们最最经常的工作就是要处理文本文件,不管是什么数据库最后都可以导成文本,我们就 ...

  2. 开涛spring3(4.1) - 资源 之 4.1 基础知识

    4.1.1  概述 在日常程序开发中,处理外部资源是很繁琐的事情,我们可能需要处理URL资源.File资源资源.ClassPath相关资源.服务器相关资源 (JBoss AS 5.x上的VFS资源)等 ...

  3. (数字IC)低功耗设计入门(六)——门级电路低功耗设计优化

    三.门级电路低功耗设计优化 (1)门级电路的功耗优化综述 门级电路的功耗优化(Gate Level Power Optimization,简称GLPO)是从已经映射的门级网表开始,对设计进行功耗的优化 ...

  4. Github 开源:使用控制器操作 WinForm/WPF 控件( Sheng.Winform.Controls.Controller)

    利用午休时间继续把过去写的一些代码翻出来说一说,文章可能写的比较简略,但是我会努力把核心意思表达清楚,具体代码可直接访问 Github 获取. Github 地址:https://github.com ...

  5. Java之JSON数据

    特别注意:使用JSON前需要导包 操作步骤地址:http://blog.csdn.net/baidu_37107022/article/details/70876993 1.定义 JSON(JavaS ...

  6. Java阶段性测试--第二三大题参考代码

    第二大题: 1.打印出所有的 "水仙花数 ",所谓 "水仙花数 "是指一个三位数,其各位数字立方和等于它本身 package Test1; //1.打印出所有的 ...

  7. Java IO流之【缓冲流和文件流复制文件对比】

    与文件流相比,缓冲流复制文件更快 代码: package Homework; import java.io.BufferedOutputStream; import java.io.File; imp ...

  8. Centos 执行shell命令返回127错误

    shell脚本功能:连接mysql,自动创建数据库,脚本如下 mysql -h$MYSQL_IP -u$MYSQL_USER -p$MYSQL_PASSWORD --default-character ...

  9. vue-cli webpack在node环境下安装使用

    第一步,需要下载并安装node.js以及他的npm组件: 第二步,用node -v;npm -v来测试node.js以及npm是否安装成功(建议用GIT命令行工具,因为GIT是linux系统),如果显 ...

  10. 利用arpspoof和urlsnarf 进行ARP嗅探

    地址解析协议 (ARP, Address Resolution Protocol) 是如何将网络设备的MAC地址和其IP地址关联起来的,这样在同一个局域网内的设备就能相互知道彼此的存在.ARP基本上就 ...