1. 程式人生 > >《STL原始碼剖析》—— stl_config.h

《STL原始碼剖析》—— stl_config.h

參考侯捷《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 */