什么是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可以在这里使用.

Header Only Library的更多相关文章

  1. 【转】Header Only Library的介绍

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

  2. Please ensure the argon2 header and library are installed

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

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

  4. c++中的header-only library

    不同于在java中,虽然在java中,有些第三方库只是做了桥接的功能,比如slf4j-log4j-api,但是在运行时他们仍然是需要的,所以最多只能说是松耦合做得很好. 但是在c++中,一般我们应用第 ...

  5. Google C++ Style Guide

    Background C++ is one of the main development languages used by many of Google's open-source project ...

  6. 关于c++风格 code style

    Header files should be self-contained. All header files should have #define guards to prevent multip ...

  7. 安装coreseek找不到mysql

    1.安装 coreseek-3.2.14 遇到问题:“ERROR: cannot find MySQL include files,随即在网上搜索各种答案说是要找到mysql.h的正确路径加入./co ...

  8. 升级openssl

    升级openssl 依赖openssl的软件,如果是静态编译openssl,那么需要重新编译软件,如果是利用openssl的so动态库,那么只需要替换一下so文件并重启软件即可 openssh也依赖o ...

  9. mysql 升级方法

    Performing an In-place Upgrade This section describes how to perform an in-place upgrade. Review Bef ...

随机推荐

  1. classpath和环境变量设置

    一.简介: 环境变量是操作系统.应用程序.脚本程序等等的指明灯,能够告诉他们需要的资源在哪里.大多数的 系统都有一些预先设置好的环境变量,当然,我们也可以增加自己的环境变量. 为了看看当前系统的环境变 ...

  2. java代码确认出ip和主机名

    总结::不懂... package com.aa; import java.net.*; public class InetAddresTest { public static void main(S ...

  3. redirect uri 参数错误 怎么办

    这种情况,多数是因为请求地址不合法所致. 去公众号中添加合法的地址. 这种地址需要满足一些条件. 设置地址 满足的条件 保证可以访问到安全文件 如果访问不到的话,将无法保存 这里是文件存放位置 经过这 ...

  4. kali下启动postgresql

    1.service postgresql start 2.su postgres 3.psql

  5. 第九章 整合Mybatis(待续)

    ··········

  6. DRF - 序列化组件(GET/PUT/DELETE接口设计)、视图优化组件

    一.序列化组件 基于上篇随笔的表结构 , 通过序列化组件的ModelSerializer设计如下三个接口 : GET 127.0.0.1:8000/books/{id} # 获取一条数据,返回值:{} ...

  7. 关于Pycharm中如何注释

    主要有三种方法: ①在程序行前面加“#” ②将需要注释的代码用'''----''' 包起来,此方法类似C的注释方法 ③将需要注释的代码选住然后利用“Ctrl+/”进行注释 # test=input(' ...

  8. : error C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

    打开项目----项目属性---配置属性----C/C++ ----预处理器----预处理定义,添加_CRT_SECURE_NO_WARNINGS

  9. OSCache安装

    OSCache是一个基于web应用的组件,他的安装工作主要是对web应用进行配置,大概的步骤如下: 1. 下载.解压缩OSCachehttps://java.net/downloads/oscache ...

  10. python文件处理-读、写

    Python中文件处理的操作包括读.写.修改,今天我们一起来先学习下读和写操作. 一.文件的读操作 例一: #文件读操作 f = open(file="first_blog.txt" ...