boost/config.hpp文件詳解


簡要概述

今天突發奇想想看一下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
  • 。。。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM