簡要概述
今天突發奇想想看一下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/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)。
平台配置文件(和每一種平台對應)
- 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/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
總體總結一下:
- BOOST_SYMBOL_EXPORT
- BOOST_SYMBOL_IMPORT
- BOOST_PLATFORM
- BOOST_STATIC_CONSTANT
- BOOST_STRINGIZE
- BOOST_JOIN
- BOOST_FORCEINLINE
- BOOST_NOINLINE
- BOOST_ALIGNMENT
- 。。。