简要概述

今天突发奇想想看一下boost/config.hpp的内部实现,以及他有哪些功能。

这个头文件都有一个类似的结构,先包含一个头文件,假设为头文件1,然后包含这个头文 件中定义的宏。对于头文件中1中,有大量的#if..#endif,在这些指定的宏块中定义一个头文件宏,在这些大量的#if...#end中,头文件宏 有且只会被定义一次。具体的定义详情在下面进行详解。

根据上面的思路分析出了,config.hpp文件中主要包含几个主要的头文件:关于 用户配置的头文件(User config)、编译器配置文件(Compiler config)、C++标准库配置文件(Standard library)、平台配置文件(Platform config)、其他零碎的配置文件。接下来描述每个头文件里面的大概作用。

用户配置文件(可控制的)

它是可选配置,可以通过定义BOOST_NO_USER_CONFIG宏来禁止包含用户配置头文件。如果没有禁止的话,那么这个头文件就是boost/config/user.hpp。

如果你没有禁止的话,那么你可以在boost/config/user.hpp中定义一些关键的宏。这个文件中默认一些被注释的宏,你可以根据需求取消这些注释,并且定义自己的配置。主要有如下宏:

  • BOOST_COMPILER_CONFIG,这个宏用来指定编译器配置的hpp文 件,他是有一定标准的,他是和编译器相关的,要定一些通用功能的宏,比如 BOOST_SYMBOL_EXPORT,BOOST_SYMBOL_IMPORT,还有一些关于编译器对于标准的支持,比如是否支持long long类型,是否支持pragma once,是否支持cxx11中的某些特性。。。,详情请参考:boost/config/compiler/gcc.hpp。一般不要定义这个宏,因为 对于主流的编译器,他都会有对应的编译器配置头文件(这个宏在下面还会介绍到)。一般是对于一种新的编译器,如果你想让他支持boost的话,那么你需要 重新定义这个宏,所以说,一般用户是不会自己定义这个宏的。
  • BOOST_STDLIB_CONFIG,这个宏用来指定
    标准库配置文件(hpp文件),主要描述一些标准库对于某些标准的支持(后面会有详细介绍的),因为Boost都主流的标准库都会自己定义对应这个hpp
    配置文件,所以一般用户不用自己定义这个宏,只有一个新的标准库的作者,可能才要定义这个宏为自己标准库的配置文件。文件样例可以参
    考:boost/config/stdlib/libstdcpp3.hpp(他是gnu自带的标准库配置文件),boost/config
    /stdlib/sgi.hpp(著名的sgi标准库配置文件)。
  • BOOST_PLATFORM_CONFIG,平台配置文
    件,普通用户不用定义,只有新的系统作者,或者某个平台作者才会定义这个文件,样例参考:boost/config/platform
    /win32.hpp(win32平台),boost/config/platform/linux.hpp(linux平台),boost
    /config/platform/bsd.hpp(bsd平台)
  • BOOST_NO_COMPILER_CONFIG,定义这个宏可以取消编译器配置
  • BOOST_NO_STDLIB_CONFIG,定义这个宏可以取消标准库配置
  • BOOST_NO_PLATFORM_CONFIG,定义这个宏可以取消平台配置
  • BOOST_NO_CONFIG,定义这个宏可以取消所有的配置
  • 。。。(详情请参看boost/config/user.hpp)

编译器配置文件(和每一个不同编译器对应)

如果用户定义了:BOOST_COMPILER_CONFIG,或者定义了
BOOST_NO_COMPILER_CONFIG,或者定义了BOOST_NO_CONFIG的,这儿boost自己就不会包含编译器配置文件。如果前
面的说的条件都没有发生,才会发生下面的事情。

先包含一个头文件boost/config
/select_compiler_config.hpp,他会根据每一个编译器自己定义的独一无二的宏(一般vc编译器会定
义:_MSC_VER,gnu编译器会定义__GNUC__。。。)来定义BOOST_COMPILER_CONFIG(这个宏在用户配置那儿可以自己定
义,只是那儿定义后,这儿就不会再定义了),这个宏指定了编译器所对应的配置文件的路径。然后在config.hpp中包含次路径。

我选择gnu编译器所对应的配置文件来简要描述一下里面定义的内容。

  • BOOST_GCC_VERSION、BOOST_GCC根据gcc的一些相关宏所一定的gcc版本号,至少是5位整数
  • BOOST_HAS_PRAGMA_ONCE
    定义它来表明编译器是否支持#pragma once指定,一般可以在头文件中定义如下结构:#ifdef BOOST_HAS_PRAGMA_ONCE  #pragma once  #endif
  • BOOST_HAS_LONG_LONG
    用来表明是否支持long long类型
  • BOOST_HAS_NRVO 用来表明编译器是否有命名返回值优化
  • BOOST_HAS_DECLSPEC 用来表明是否支持特别声明
  • BOOST_SYMBOL_IMPORT 导出签名
  • BOOST_SYMBOL_EXPORT
    导入签名
  • 当然还有一些其他的工具宏

  • 有一些对于cxx11的某些特性的支持,如果不支持某些特性,就会定义一些特定的宏,比如:BOOST_NO_CXX11_DECLTYPE表明编译器不
    支持decltype操作符,BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS表明编译器不支持函数魔板默
    认参数。BOOST_NO_CXX11_RVALUE_REFERENCES表明编译器不支持右值引用。。。
  • 还有一些对于cxx14标准的支持。详情请参考此hpp文件
  • BOOST_ATTRIBUTE_UNUSED,指定某些签名为未使用属性
  • BOOST_COMPILER 表明某种编译器类型的字符串,比如对于gnu编译器,该字符串为"GNU C++ version " __VERSION__

简单小结:BOOST_HAS_PRAGMA_ONCE可以帮助你有选择的使
用#pragma
once,BOOST_SYMBOL_IMPORT,BOOST_SYMBOL_EXPORT可以让你不在忙于记住不同编译器的导入导出签名指令。
BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS。。。这些类似宏,可以让你有选择地使用某些cxx11中
的特性而不会出错。

标准库配置文件(和每一种标准库对应)

如果用户定义了:BOOST_STDLIB_CONFIG,或者定义了BOOST_NO_STDLIB_CONFIG,或者定义了BOOST_NO_CONFIG的,这儿boost自己就不会包含编译器配置文件。如果前面的说的条件都没有发生,才会发生下面的事情。

先包含boost/config
/select_stdlib_config.hpp,在这儿文件中和boost/config/select_compiler_config.hpp
中结构比较类似,都含有大量的if
endif预处理指定,只是这儿的用来作为条件的宏是标准类型,比如如果使用__SGI_STL_PORT(即sgi标准库)他会将
BOOST_STDLIB_CONFIG设置为
"boost/config/stdlib/stlport.hpp",如果使用__GLIBCPP__(gnu自带标准库),他会将
BOOST_STDLIB_CONFIG宏定义为:
"boost/config/stdlib/libstdcpp3.hpp"。然后会包含#include BOOST_STDLIB_CONFIG。

接下来,我会选择gnu标准库配置文件(boost/config/stdlib/libstdcpp3.hpp)来进行简要介绍配置文件里面的内容:

  • BOOST_GNU_STDLIB 1 定义它来表明使用gnu标准库
  • BOOST_STDLIB "GNU libstdc++ version " BOOST_STRINGIZE(__GLIBCXX__)定义BOOST_STDLIB 为对应的标准库字符串形式
  • BOOST_HAS_THREADS 表明支持线程
  • BOOST_STD_EXTENSION_NAMESPACE __gnu_cxx定义拓展命名空间
  • BOOST_HAS_SLIST 支持单向链表(拓展的,不在std库中)
  • BOOST_HAS_HASH 支持hash表(拓展的,不在std库中)
  • BOOST_SLIST_HEADER单向列表头文件,可以用来被包含
  • BOOST_HASH_SET_HEADER <backward/hash_set>  hash表头文件
  • BOOST_HASH_MAP_HEADER <backward/hash_map> hashmap头文件
  • BOOST_LIBSTDCXX_VERSION cxx版本,是数字
  • 下面会有一些对于cxx11标准库的支持,比
    如:BOOST_NO_CXX11_HDR_FORWARD_LIST,BOOST_NO_CXX11_HDR_INITIALIZER_LIST。。。
    详情参考此文件(boost/config/stdlib/libstdcpp3.hpp)。
简单小结一下:我上面标出的红色的部分,在cxx11标准没有出来之前,还是很重要的,但是现实随着各大编译器厂商对于cxx11标准的强有力支持中,这些特性已经可有可无了,当然对于那儿仍然在使用老的编译器进行生产的项目中还是比较重要的。

平台配置文件(和每一种平台对应)

如果用户定义了:BOOST_PLATFORM_CONFIG,或者定义了
BOOST_NO_PLATFORM_CONFIG,或者定义了BOOST_NO_CONFIG的,这儿boost自己就不会包含编译器配置文件。如果前
面的说的条件都没有发生,才会发生下面的事情。
先包含boost/config
/select_platform_config.hpp,结构和上面所描述的两个hpp文件完全相同(boost/config
/select_stdlib_config.hpp、boost/config/select_compiler_config.hpp)。逻辑就是在
这个hpp文件中,根据每一种平台所特别定义的宏来设置平台配置文件路径给BOOST_PLATFORM_CONFIG宏,然后在config.hpp文
件中包含这个宏。
接下来,我选择win32平台所对应的配置文件(boost/config/platform/win32.hpp)进行描述。
  • BOOST_PLATFORM
    "Win32" 表明了平台的字符串名称
  • 如果编译器支持__declspec(dllexport/import)的话,那么会在这儿定义BOOST_SYMBOL_EXPORT/IMPORT
  • BOOST_HAS_STDINT_H、BOOST_HAS_DIRENT_H、BOOST_HAS_UNISTD_H表明有某些头文件
  • BOOST_HAS_GETTIMEOFDAY、BOOST_HAS_WINTHREADS、BOOST_HAS_GETSYSTEMTIMEASFILETIME、BOOST_HAS_THREADEX。。。对于某些特性或者函数的支持
  • BOOST_WINDOWS
    1 也可以用来标识win32平台
  • 还有一些其他的东西,详情请参阅boost/config/platform/win32.hpp。
简单总结:利用BOOST_PLATFORM 宏,来打印平台的名称,可以使用BOOST_WINDOWS 来作为#if的条件,来进行选择编译。

其他一些补充配置文件(固定的:boost/config/suffix.hpp)(包含了大量常用跨平台(编译器)宏)

  • 有一些关于编译器特性支持的宏,比如
    BOOST_NO_MS_INT64_NUMERIC_LIMITS
    表明不支持numeric_limit<__int64>,BOOST_MSVC6_MEMBER_TEMPLATES
    用来表明不支持成员函数模板,BOOST_HAS_PARTIAL_STD_ALLOCATOR 表明有一个局部的标准分配器。。。
  • 有一些工具宏:BOOST_USING_STD_MIN/MAX使用std::min/max来计算最小值和最大值,BOOST_STATIC_CONSTANT定义静态常量
  • BOOST_STRINGIZE(X) 将x转换为字符串形式
  • BOOST_JOIN(X, Y) 可以讲X和Y链接成一个符号比如BOOST_JOIN(My, Dog)会变成MyDog符号
  • 还有一些对于编译器行为的控制:比如:BOOST_FORCEINLINE强制内联,BOOST_NOINLINE阻止函数内联。BOOST_ALIGNMENT(x)设置内存对其方式。
  • 还有一些描述cxx11的是否支持某些特性的宏
  • 详情请看boost/config/suffix.hpp
简单总结:这个hpp文件非常非常重要,他几乎提供了80%以上的跨平台的可以使
用的宏。包含了编译器对一些基本类型的支持,对于cxx11标准的支持。并且提供了一些统一的控制编译器行为的宏,和一些比较方便的工具宏。
值得看一下这个文件里面所定义的宏,没准以后就有类似的需求,可以使用里面的宏来解决问题。

总体总结一下:

1)、以前打开文本编译器看config.hpp这个头文件,进入头文件中,看到一大堆#if..#endif,头就晕,其实借助Ide的话,层次就非常清晰了,我使用eclipse,看一下他构建的Index索引数,1分钟就知道他的结构了。
2)、就包含四个文件,也上面文章的4大部分:用户配置文件(他只对 编译器开发人员,标准库设计人员,平台设计人员),编译器配置文件,平台配置文件,补充文件(工具)。
3)、
可以使用config来检测编译器对于某些特性的支持,比如是否支持pragma once指定,是否支持long
long类型。也可以检测标准库是否支持某些cxx11中的标准特性。还可以检测某个平台对于某些基本类型的支持,某些函数的支持。可以利用他提供的工具
宏来控制各种编译器的行为,是真正的编译器啊!!!!。
4)、列出个人认为比较有用的宏(基本上都是工具宏):
  • BOOST_SYMBOL_EXPORT
  • BOOST_SYMBOL_IMPORT
  • BOOST_PLATFORM
  • BOOST_STATIC_CONSTANT
  • BOOST_STRINGIZE
  • BOOST_JOIN
  • BOOST_FORCEINLINE
  • BOOST_NOINLINE
  • BOOST_ALIGNMENT
  • 。。。

boost/config.hpp文件详解的更多相关文章

  1. C#中web.config文件详解

    C#中web.config文件详解 一.认识Web.config文件 Web.config 文件是一个XML文本文件,它用来储存 ASP.NET Web 应用程序的配置信息(如最常用的设置ASP.NE ...

  2. web.xml文件详解

      web.xml文件详解 Table of Contents 1 listener. filter.servlet 加载顺序 2 web.xml文件详解 3 相应元素配置 1 listener. f ...

  3. Android.mk文件详解(转)

    源:Android.mk文件详解 从对Makefile一无所知开始,折腾了一个多星期,终于对Android.mk有了一个全面些的了解.了解了标准的Makefile后,发现Android.mk其实是把真 ...

  4. 附005.Docker Compose文件详解

    一 Docker Compose文件简介 compose文件使用yml格式,主要分为了四个区域: version:用于指定当前docker-compose.yml语法遵循哪个版本 services:服 ...

  5. Angular Npm Package.Json文件详解

    Angular7 Npm Package.Json文件详解   近期时间比较充裕,正好想了解下Angular Project相关内容.于是将Npm官网上关于Package.json的官方说明文档进行了 ...

  6. tomcat 加载顺序 web.xml文件详解

    一. 1.启动一个WEB项目的时候,WEB容器会去读取它的配置文件web.xml,读取<listener>和<context-param>两个结点. 2.紧急着,容创建一个Se ...

  7. Git的gitattributes文件详解

    转自:Git的gitattributes文件详解 Git的gitattributes文件是一个文本文件,文件中的一行定义一个路径的若干个属性. 1. gitattributes文件以行为单位设置一个路 ...

  8. vue-cli生成的模板各个文件详解(转)

    vue-cli脚手架中webpack配置基础文件详解 一.前言 原文:https://segmentfault.com/a/1190000014804826 vue-cli是构建vue单页应用的脚手架 ...

  9. Linux-apache httd.conf文件详解

    Linux-apache httd.conf文件详解 # This is the main Apache server configuration file. It contains the # co ...

随机推荐

  1. 洛谷 P2797 Facer的魔法 解题报告

    P2797 Facer的魔法 题意:给你n个数,你可以选若干个数,使得平均数减中位数最大 数据范围:\(n \le 10^5\) 原题CF626E 很容易想到枚举一个中位数,但是如果选取的数字的个数是 ...

  2. poj 3311 floyd+dfs或状态压缩dp 两种方法

    Hie with the Pie Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 6436   Accepted: 3470 ...

  3. spring in action 学习笔记二:aop的理解

    一: aop的思想的来在哪里? 一个系统一般情况下由多个组件组成,而每一个组件除了干自己的本职工作以外,有时还会干一些杂活(如:日志(logging).事务管理(transaction manager ...

  4. mac 安装 nodeJs&npm 配置

    前言:继续安装 nodeJS 下载安装:直接去官网,点击安装即可. 命令式安装: 1. 安装 homebrew 2. 安装 nodeJS,使用命令:brew install node 3. 测试 no ...

  5. [1]区分event对象中的[clientX,offsetX,screenX,pageX]

    前言 在平时的开发中,非常讨厌的就是兼容性了,兼容性的问题总会让我们记忆混淆,所以这次来区分一下event对象中的常用获取鼠标位置. clientX clientY event.clientXeven ...

  6. 转:LinkedHashMap使用(可以用来实现LRU缓存)

    1. LinkedHashMap概述: LinkedHashMap是HashMap的一个子类,它保留插入的顺序,如果需要输出的顺序和输入时的相同,那么就选用LinkedHashMap. LinkedH ...

  7. Topcoder SRM 601 div1题解

    日常TC计划- Easy(250pts): 题目大意:有n个篮子,每个篮子有若干个苹果和橘子,先任取一个正整数x,然后从每个篮子中选出x个水果,把nx个水果放在一起,输出一共有多少种不同的组成方案.其 ...

  8. noi2017 T1 整数 ——线段树

    loj.ac上有  题目传送门 不过我还是把题目搬过来吧 整数(integer)[题目背景]在人类智慧的山巅,有着一台字长为 1048576 位的超级计算机,著名理论计算机科 学家 P 博士正用它进行 ...

  9. 洛谷P1450 [HAOI2008]硬币购物

    题目描述 硬币购物一共有4种硬币.面值分别为c1,c2,c3,c4.某人去商店买东西,去了tot次.每次带di枚ci硬币,买si的价值的东西.请问每次有多少种付款方法. 输入输出格式 输入格式: 第一 ...

  10. Appium+python自动化19-iOS模拟器(iOS Simulator)安装自家APP【转载】

    前言 做过iOS上app测试的小伙伴应该都知道,普通用户安装app都是从appstore下载安装,安装测试版本的app,一般就是开发给的二维码扫码安装, 或者开发给个.ipa的安装包文件,通过itoo ...