boost/config.hpp文件詳解

簡要概述

今天突發奇想一想看一下boost/config.hpp的內部實現,以及他有哪些功能。linux

這個頭文件都有一個相似的結構,先包含一個頭文件,假設爲頭文件1,而後包含這個頭文 件中定義的宏。對於頭文件中1中,有大量的#if..#endif,在這些指定的宏塊中定義一個頭文件宏,在這些大量的#if...#end中,頭文件宏 有且只會被定義一次。具體的定義詳情在下面進行詳解。c++

根據上面的思路分析出了,config.hpp文件中主要包含幾個主要的頭文件:關於 用戶配置的頭文件(User config)、編譯器配置文件(Compiler config)、C++標準庫配置文件(Standard library)、平臺配置文件(Platform config)、其餘零碎的配置文件。接下來描述每一個頭文件裏面的大概做用。eclipse

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

它是可選配置,能夠經過定義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編譯器所對應的配置文件來簡要描述一下里面定義的內容。spa

  • 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。orm

接下來,我會選擇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
  • 。。。
相關文章
相關標籤/搜索