《STL原始碼剖析》—— stl_config.h
阿新 • • 發佈:2019-02-06
參考侯捷《STL原始碼剖析》 #ifndef __STL_CONFIG_H # define __STL_CONFIG_H // 本檔案所做的事情: // (1) 如果編譯器沒有定義 bool,true,false,就定義它們 // (2) 如果編譯器的標準程式庫未支援 drand48() 函式,就定義 __STL_NO_DRAND48 // (3) 如果編譯器無法處理 static member of template classes(模板類的靜態成員),就定義 __STL_STATIC_TEMPLATE_MEMBER_BUG // (4) 如果編譯器未支援關鍵詞 typename,就將‘typename’定義為一個 null macro(空的巨集). // (5) 如果編譯器支援 partial specialization of class templates(模板類的部分特化), // 就定義 __STL_CLASS_PARTIAL_SPECIALIZATION. // (6) 如果編譯器支援 partial ordering of function templates (亦稱為 partial specialization of function templates), // 就定義 __STL_FUNCTION_TMPL_PARTIAL_ORDER // (7) 如果編譯器允許我們在呼叫一個 function template 時可以明白指定其 template arguments, // 就定義__STL_EXPLICIT_FUNCTION_TMPL_ARGS // (8) 如果編譯器支援 template members of classes,就定義 __STL_MEMBER_TEMPLATES // (9) 如果編譯器不支援關鍵詞 explicit ,就定義 ‘explicit’為一個 null macro. // (10) 如果編譯器無法根據前一個 template parameters 設定下一個 template parameters 的預設值, // 就定義 __STL_LIMITED_DEFAULT_TEMPLATES // (11) 如果編譯器針對 non-type template parameters 執行 function template 的引數推導(argument deduction)時有問題, // 就定義 __STL_NON_TYPE_TMPL_PARAM_BUG // (12) 如果編譯器無法支援迭代器的 operator->,就定義 __SGI_STL_NO_ARROW_OPERATOR // (13) 如果編譯器(在你所選擇的模式中)支援 exceptions,就定義 __STL_USE_EXCEPTIONS // (14) 如果我們將 STL 放入名稱空間中,則定義 __STL_USE_NAMESPACES // (15) 如果本程式庫由 SGI 編譯器來編譯,並且使用這並未選擇 pthreads 或其他 threads,就定義 __STL_SGI_THREADS // (16) 如果本程式由一個 WIN32 編譯器編譯,並且在多執行緒模式下,就定義 __STL_WIN32THREADS // (17) 適當地定義與namespace 相關的 macros (如 __STD, __STL_BEGIN_NAMESPACE, 等.) // (18) 適當地定義與exception 相關的 macros (如 __STL_TRY, __STL_UNWIND, 等.) // (19) 根據 __STL_ASSERTIONS 是否定義,將 __stl_assert 定義為一個測試操作或一個 null macro // 通過對上面註釋的翻譯,知道該檔案會根據各家不同的編譯器以及可能的不同版本,給予一些常量的定義。 // 這些常量中絕大部分都與模板(template)相關,包括 3,5,6,7,8,10,11 #ifdef _PTHREADS # define __STL_PTHREADS #endif // 使用 SGI STL 但卻不是用 GNU C++:這裡如果我們在Linux下編譯SGI STL的話,下面包括的內容就可以不用考慮。 // 因為Linux上的編譯器就是 GNU C++ # if defined(__sgi) && !defined(__GNUC__) # if !defined(_BOOL) # define __STL_NEED_BOOL # endif # if !defined(_TYPENAME_IS_KEYWORD) # define __STL_NEED_TYPENAME # endif # ifdef _PARTIAL_SPECIALIZATION_OF_CLASS_TEMPLATES # define __STL_CLASS_PARTIAL_SPECIALIZATION # endif # ifdef _MEMBER_TEMPLATES # define __STL_MEMBER_TEMPLATES # endif # if !defined(_EXPLICIT_IS_KEYWORD) # define __STL_NEED_EXPLICIT # endif # ifdef __EXCEPTIONS # define __STL_USE_EXCEPTIONS # endif # if (_COMPILER_VERSION >= 721) && defined(_NAMESPACES) # define __STL_USE_NAMESPACES # endif # if !defined(_NOTHREADS) && !defined(__STL_PTHREADS) # define __STL_SGI_THREADS # endif # endif // 下面是GNU C++ 編譯器,從下面可以看出如果版本低於 2.8 的GNU C++ 和高於 2.8 版本的之間的不同, // 例如高於2.8的版本支援類中的模板成員了(因為定義了_STL_MEMBER_TEMPLATES) # ifdef __GNUC__ # include <_G_config.h> # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8) # define __STL_STATIC_TEMPLATE_MEMBER_BUG # define __STL_NEED_TYPENAME # define __STL_NEED_EXPLICIT # else # define __STL_CLASS_PARTIAL_SPECIALIZATION # define __STL_FUNCTION_TMPL_PARTIAL_ORDER # define __STL_EXPLICIT_FUNCTION_TMPL_ARGS # define __STL_MEMBER_TEMPLATES # endif /* glibc pre 2.0 is very buggy. We have to disable thread for it. It should be upgraded to glibc 2.0 or later. */ # if !defined(_NOTHREADS) && __GLIBC__ >= 2 && defined(_G_USING_THUNKS) # define __STL_PTHREADS # endif # ifdef __EXCEPTIONS # define __STL_USE_EXCEPTIONS # endif # endif # if defined(__SUNPRO_CC) # define __STL_NEED_BOOL # define __STL_NEED_TYPENAME # define __STL_NEED_EXPLICIT # define __STL_USE_EXCEPTIONS # endif # if defined(__COMO__) # define __STL_MEMBER_TEMPLATES # define __STL_CLASS_PARTIAL_SPECIALIZATION # define __STL_USE_EXCEPTIONS # define __STL_USE_NAMESPACES # endif // 下面是 VC 編譯器的部分 # if defined(_MSC_VER) # if _MSC_VER > 1000 # include <yvals.h> # else # define __STL_NEED_BOOL # endif # define __STL_NO_DRAND48 # define __STL_NEED_TYPENAME # if _MSC_VER < 1100 # define __STL_NEED_EXPLICIT # endif # define __STL_NON_TYPE_TMPL_PARAM_BUG # define __SGI_STL_NO_ARROW_OPERATOR # ifdef _CPPUNWIND # define __STL_USE_EXCEPTIONS # endif # ifdef _MT # define __STL_WIN32THREADS # endif # endif # if defined(__BORLANDC__) # define __STL_NO_DRAND48 # define __STL_NEED_TYPENAME # define __STL_LIMITED_DEFAULT_TEMPLATES # define __SGI_STL_NO_ARROW_OPERATOR # define __STL_NON_TYPE_TMPL_PARAM_BUG # ifdef _CPPUNWIND # define __STL_USE_EXCEPTIONS # endif # ifdef __MT__ # define __STL_WIN32THREADS # endif # endif // 從這裡開始,編譯器特性的分析已經結束了,需要對分析結果進行處理了。 # if defined(__STL_NEED_BOOL) typedef int bool; # define true 1 # define false 0 # endif # ifdef __STL_NEED_TYPENAME # define typename # endif # ifdef __STL_NEED_EXPLICIT # define explicit # endif # ifdef __STL_EXPLICIT_FUNCTION_TMPL_ARGS # define __STL_NULL_TMPL_ARGS <> # else # define __STL_NULL_TMPL_ARGS # endif # ifdef __STL_CLASS_PARTIAL_SPECIALIZATION # define __STL_TEMPLATE_NULL template<> # else # define __STL_TEMPLATE_NULL # endif // 註釋(14) // __STL_NO_NAMESPACES is a hook so that users can disable namespaces // without having to edit library headers. # if defined(__STL_USE_NAMESPACES) && !defined(__STL_NO_NAMESPACES) # define __STD std # define __STL_BEGIN_NAMESPACE namespace std { # define __STL_END_NAMESPACE } # define __STL_USE_NAMESPACE_FOR_RELOPS # define __STL_BEGIN_RELOPS_NAMESPACE namespace std { # define __STL_END_RELOPS_NAMESPACE } # define __STD_RELOPS std # else # define __STD # define __STL_BEGIN_NAMESPACE # define __STL_END_NAMESPACE # undef __STL_USE_NAMESPACE_FOR_RELOPS # define __STL_BEGIN_RELOPS_NAMESPACE # define __STL_END_RELOPS_NAMESPACE # define __STD_RELOPS # endif // 註釋(18) # ifdef __STL_USE_EXCEPTIONS # define __STL_TRY try # define __STL_CATCH_ALL catch(...) # define __STL_RETHROW throw # define __STL_NOTHROW throw() # define __STL_UNWIND(action) catch(...) { action; throw; } # else # define __STL_TRY # define __STL_CATCH_ALL if (false) # define __STL_RETHROW # define __STL_NOTHROW # define __STL_UNWIND(action) # endif // 註釋(19) #ifdef __STL_ASSERTIONS # include <stdio.h> # define __stl_assert(expr) \ if (!(expr)) { fprintf(stderr, "%s:%d STL assertion failure: %s\n", \ __FILE__, __LINE__, # expr); abort(); } #else # define __stl_assert(expr) #endif #endif /* __STL_CONFIG_H */