首页 > 代码库 > STL源码剖析—stl_config

STL源码剖析—stl_config

操作系统:centos 6.4
STL源码版本:3.3

前言:
    要看一个项目的源码,首先要选中切入点。
    那么在sgi stl 标准库中,其切入点是什么呢?
    答案是:stl_config.h 文件。

    不同的编译器对C++语言的支持程度不尽相同。为了具备广泛移植能力,SGI STL  定义了一个环境组态文件<stl_config.h>。
其中声明了许多宏定义,在预编译的时候,通过这些宏定义来编译出对于平台的程序。


1,stl_config.h在linux平台下的实现:
    
    1.1)为了知道linux平台下sgi stl 的宏定义有那些是被定义了的,有个简单,直接的方法,直接输出其宏名字。
        测试代码如下:

#include <iostream>#include <stdio.h>using namespace std;void    test(void){#ifdef _PTHREADS    cout<<"define __STL_PTHREADS"<<endl;#endif# if defined(__sgi) && !defined(__GNUC__)    cout<<"__sgi begin"<<endl;# if !defined(_BOOL)        cout<<"__STL_NEED_BOOL"<<endl;# endif# if !defined(_TYPENAME_IS_KEYWORD)         cout<<"__STL_NEED_TYPENAME"<<endl;# endif# ifdef _PARTIAL_SPECIALIZATION_OF_CLASS_TEMPLATES        cout<<"__STL_CLASS_PARTIAL_SPECIALIZATION"<<endl;# endif# ifdef _MEMBER_TEMPLATES        cout<<"__STL_MEMBER_TEMPLATES"<<endl;# endif# if !defined(_EXPLICIT_IS_KEYWORD)        cout<<"__STL_NEED_EXPLICIT"<<endl;# endif# ifdef __EXCEPTIONS        cout<<"__STL_USE_EXCEPTIONS"<<endl;# endif# if (_COMPILER_VERSION >= 721) && defined(_NAMESPACES)        cout<<"__STL_USE_NAMESPACES"<<endl;# endif # if !defined(_NOTHREADS) && !defined(__STL_PTHREADS)        cout<<"__STL_SGI_THREADS"<<endl;# endif    cout<<"__sgi end"<<endl<<endl;# endif# ifdef __GNUC__    cout<<"__GNUC__ begin"<<endl;# include <_G_config.h># if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)        cout<<"__STL_STATIC_TEMPLATE_MEMBER_BUG"<<endl;        cout<<"__STL_NEED_TYPENAME"<<endl;        cout<<"__STL_NEED_EXPLICIT"<<endl;# else        cout<<"__STL_CLASS_PARTIAL_SPECIALIZATION"<<endl;        cout<<"__STL_FUNCTION_TMPL_PARTIAL_ORDER"<<endl;        cout<<"__STL_EXPLICIT_FUNCTION_TMPL_ARGS"<<endl;        cout<<"__STL_MEMBER_TEMPLATES"<<endl;# 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)        cout<<"__STL_PTHREADS"<<endl;# endif# ifdef __EXCEPTIONS        cout<<"__STL_USE_EXCEPTIONS"<<endl;# endif    cout<<"__GNUC__ end"<<endl<<endl;# endif# if defined(__SUNPRO_CC)     cout<<"__SUNPRO_CC begin"<<endl;    cout<<"__STL_NEED_BOOL"<<endl;    cout<<"__STL_NEED_TYPENAME"<<endl;    cout<<"__STL_NEED_EXPLICIT"<<endl;    cout<<"__STL_USE_EXCEPTIONS"<<endl;    cout<<"__SUNPRO_CC end"<<endl<<endl;# endif# if defined(__COMO__)    cout<<"__COMO__ begin"<<endl;    cout<<"__STL_MEMBER_TEMPLATES"<<endl;    cout<<"__STL_CLASS_PARTIAL_SPECIALIZATION"<<endl;    cout<<"__STL_USE_EXCEPTIONS"<<endl;    cout<<"__STL_USE_NAMESPACES"<<endl;    cout<<"__COMO__ end"<<endl<<endl;# endif# if defined(_MSC_VER)cout<<"_MSC_VER begin"<<endl;# if _MSC_VER > 1000        cout<<"include <yvals.h>"<<endl;# else        cout<<"__STL_NEED_BOOL"<<endl;# endif        cout<<"__STL_NO_DRAND48"<<endl;        cout<<"__STL_NEED_TYPENAME"<<endl;# if _MSC_VER < 1100        cout<<"__STL_NEED_EXPLICIT"<<endl;# endif        cout<<"__STL_NON_TYPE_TMPL_PARAM_BUG"<<endl;        cout<<"__SGI_STL_NO_ARROW_OPERATOR"<<endl;# ifdef _CPPUNWIND        cout<<"__STL_USE_EXCEPTIONS"<<endl;# endif# ifdef _MT        cout<<"__STL_WIN32THREADS"<<endl;# endif    cout<<"_MSC_VER end"<<endl<<endl;# endif# if defined(__BORLANDC__)    cout<<"__BORLANDC__ begin"<<endl;    cout<<"__STL_NO_DRAND48"<<endl;    cout<<"__STL_NEED_TYPENAME"<<endl;    cout<<"__STL_LIMITED_DEFAULT_TEMPLATES"<<endl;    cout<<"__SGI_STL_NO_ARROW_OPERATOR"<<endl;    cout<<"__STL_NON_TYPE_TMPL_PARAM_BUG"<<endl;# ifdef _CPPUNWIND        cout<<"__STL_USE_EXCEPTIONS"<<endl;# endif# ifdef __MT__        cout<<"__STL_WIN32THREADS"<<endl;# endif    cout<<"__BORLANDC__ end"<<endl<<endl;# endif# if defined(__STL_NEED_BOOL)    cout<<"__STL_NEED_BOOL begin"<<endl;    cout<<"typedef int bool;"<<endl;    cout<<"define true 1"<<endl;    cout<<"define false 0"<<endl;    cout<<"__STL_NEED_BOOL end"<<endl<<endl;# endif# ifdef __STL_NEED_TYPENAME    cout<<"define typename"<<endl;# endif# ifdef __STL_NEED_EXPLICIT    cout<<"define explicit"<<endl;# endif# ifdef __STL_EXPLICIT_FUNCTION_TMPL_ARGS    cout<<"__STL_NULL_TMPL_ARGS <>"<<endl;# else    cout<<"__STL_NULL_TMPL_ARGS"<<endl;# endif# ifdef __STL_CLASS_PARTIAL_SPECIALIZATION    cout<<"__STL_TEMPLATE_NULL template<>"<<endl;# else    cout<<"__STL_TEMPLATE_NULL"<<endl;# endif// __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)    cout<<"__STL_USE_NAMESPACES begin"<<endl;    cout<<"__STD std"<<endl;    cout<<"__STL_BEGIN_NAMESPACE namespace std {"<<endl;    cout<<"__STL_END_NAMESPACE }"<<endl;    cout<<"__STL_USE_NAMESPACE_FOR_RELOPS"<<endl;    cout<<"__STL_BEGIN_RELOPS_NAMESPACE namespace std {"<<endl;    cout<<"__STL_END_RELOPS_NAMESPACE }"<<endl;    cout<<"__STD_RELOPS std"<<endl;    cout<<"__STL_USE_NAMESPACES end"<<endl<<endl;# else    cout<<"! __STL_USE_NAMESPACES begin"<<endl;    cout<<"__STD "<<endl;    cout<<"__STL_BEGIN_NAMESPACE "<<endl;    cout<<"__STL_END_NAMESPACE "<<endl;    cout<<"__STL_USE_NAMESPACE_FOR_RELOPS"<<endl;    cout<<"__STL_BEGIN_RELOPS_NAMESPACE "<<endl;    cout<<"__STL_END_RELOPS_NAMESPACE "<<endl;    cout<<"__STD_RELOPS "<<endl;    cout<<"! __STL_USE_NAMESPACES end"<<endl<<endl;# endif# ifdef __STL_USE_EXCEPTIONS    cout<<"__STL_USE_EXCEPTIONS begin"<<endl;    cout<<"__STL_TRY try"<<endl;    cout<<"__STL_CATCH_ALL catch(...)"<<endl;    cout<<"__STL_RETHROW throw"<<endl;    cout<<"__STL_NOTHROW throw()"<<endl;    cout<<"__STL_UNWIND(action) catch(...) { action; throw; }"<<endl;    cout<<"__STL_USE_EXCEPTIONS end"<<endl<<endl;# else    cout<<"! __STL_USE_EXCEPTIONS begin"<<endl;    cout<<"__STL_TRY "<<endl;    cout<<"__STL_CATCH_ALL if (false)"<<endl;    cout<<"__STL_RETHROW "<<endl;    cout<<"__STL_NOTHROW "<<endl;    cout<<"__STL_UNWIND(action) "<<endl;    cout<<"! __STL_USE_EXCEPTIONS end"<<endl<<endl;# endif#ifdef __STL_ASSERTIONS# include <stdio.h>    cout<<"__stl_assert(expr) \    if (!(expr)) { fprintf(stderr, \"%s:%d STL assertion failure: %s\n\", \             __FILE__, __LINE__, # expr); abort(); }"<<endl;#else    cout<<"__stl_assert(expr)"<<endl;#endif}int main(void){    test();    return 0;}

运行结果:

[root@localhost stlsource]# g++ -o lconfig1 lconfig1.cpp [root@localhost stlsource]# ./lconfig1 __GNUC__ begin__STL_CLASS_PARTIAL_SPECIALIZATION__STL_FUNCTION_TMPL_PARTIAL_ORDER__STL_EXPLICIT_FUNCTION_TMPL_ARGS__STL_MEMBER_TEMPLATES__STL_PTHREADS__STL_USE_EXCEPTIONS__GNUC__ end__STL_NULL_TMPL_ARGS__STL_TEMPLATE_NULL! __STL_USE_NAMESPACES begin__STD __STL_BEGIN_NAMESPACE __STL_END_NAMESPACE __STL_USE_NAMESPACE_FOR_RELOPS__STL_BEGIN_RELOPS_NAMESPACE __STL_END_RELOPS_NAMESPACE __STD_RELOPS ! __STL_USE_NAMESPACES end! __STL_USE_EXCEPTIONS begin__STL_TRY __STL_CATCH_ALL if (false)__STL_RETHROW __STL_NOTHROW __STL_UNWIND(action) ! __STL_USE_EXCEPTIONS end__stl_assert(expr)

   1.2)通过以上的测试,可以得到在linux平台下,stl_config.h 的实现定义如下:
        为了缩小篇幅,把相关的版权信息的屏蔽了。

#ifndef __STL_CONFIG_H# define __STL_CONFIG_H# ifdef __GNUC__# include <_G_config.h># define __STL_CLASS_PARTIAL_SPECIALIZATION# define __STL_FUNCTION_TMPL_PARTIAL_ORDER# define __STL_EXPLICIT_FUNCTION_TMPL_ARGS# define __STL_MEMBER_TEMPLATES# define __STL_PTHREADS# define __STL_USE_EXCEPTIONS# endif# define __STL_NULL_TMPL_ARGS# define __STL_TEMPLATE_NULL# 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 # define __STL_TRY # define __STL_CATCH_ALL if (false)# define __STL_RETHROW # define __STL_NOTHROW # define __STL_UNWIND(action) # define __stl_assert(expr)#endif /* __STL_CONFIG_H */// Local Variables:// mode:C++// End:

2,对stl_config.h中的宏的详解
    2.1)__STL_STATIC_TEMPLATE_MEMBER_BUG 

    1. 如果编译器不支持static members of template classes(模板类静态成员),  
    2. //       则定义__STL_STATIC_TEMPLATE_MEMBER_BUG 
#include<iostream>using namespace std;template <typename T>class testClass {public:    static int _data;};//只对成员实现特化,记得加上template<>template<>int testClass<int>::_data=http://www.mamicode.com/1;template<>int testClass<char>::_data=http://www.mamicode.com/2;int main(){    cout<<testClass<int>::_data<<endl;    cout<<testClass<char>::_data<<endl;    testClass<int> Obji1,Obji2;    testClass<char> Objc1,Objc2;    cout<<Obji1._data<<endl;    cout<<Obji2._data<<endl;    cout<<Objc1._data<<endl;    cout<<Objc2._data<<endl;    Obji1._data=3;    Objc1._data=4;    cout<<Obji1._data<<endl;    cout<<Obji2._data<<endl;    cout<<Objc1._data<<endl;    cout<<Objc2._data<<endl;}

运行结果:

[root@localhost stlsource]# ./lconfig3 1211223344

   2.2)__STL_CLASS_PARTIAL_SPECIALIZATION

    1. 如果编译器支持partial specialization of class templates(局部特殊化的类模板),  
    2. //       则定义__STL_CLASS_PARTIAL_SPECIALIZATION  
    3. //       参考文献: http://msdn.microsoft.com/en-us/library/9w7t3kf1(v=VS.71).aspx 
#include<iostream>using namespace std;template <class I,class O>struct testClass{    testClass() {cout<<"I,O"<<endl;}};//对类实现偏特化template <class T>struct testClass<T*,T*>{    testClass() {cout<<"T*,T*"<<endl;}};//对类实现偏特化template<class T>struct testClass<const T*,T*>{    testClass(){ cout<<"const T*,T*"<<endl;}};int main(){    testClass<int,char> obj1;    testClass<int*,int*> obj2;    testClass<const int*,int*> obj3;}

运行结果:

[root@localhost stlsource]# ./lconfig5I,OT*,T*const T*,T*

    2.3)__STL_FUNCTION_TMPL_PARTIAL_ORDER

    1. 如果编译器支持partial ordering of function templates(部分排序函数模板),  
    2. //       则定义__STL_FUNCTION_TMPL_PARTIAL_ORDER  
    3. //       参考资料: http://msdn.microsoft.com/zh-cn/library/zaycz069.aspx 
#include<iostream>using namespace std;class alloc{};template <class T,class Alloc=alloc>class vector{public:    void swap(vector<T,Alloc>&) {cout<<"swap()"<<endl;}};//本来是#ifdef__STL_FUNCION_TMPL_PARTIAL_ORDER,但是貌似不支持#ifndef __STL_FUNCION_TMPL_PARTIAL_ORDERtemplate <class T,class Alloc>inline void swap(vector<T,Alloc>& x,vector<T,Alloc>& y){    x.swap(y);}#endif // __STL_FUNCION_TMPL_PARTIAL_ORDERint main(){    vector<int>x,y;    swap(x,y);}

运行结果:

[root@localhost stlsource]# ./lconfig6 swap()

    2.4)__STL_EXPLICIT_FUNCTION_TMPL_ARGS 
        整个 SGI STL  内都没有用到此一常数定义

    1. 如果编译器支持calling a function template by providing its template  
    2. //       arguments explicitly(显式指定调用模板函数的模板参数) 

    2.5)__STL_MEMBER_TEMPLATES 

  1. 如果编译器支持template members of classes(类模板成员),  
  2. //       则定义__STL_MEMBER_TEMPLATES 
#include<iostream>#include<typeinfo>using namespace std;class alloc{};//类模板template <typename T,typename Alloc=alloc>class vector{public:    typedef T value_type;    typedef value_type* iterator;//函数模板    template <typename I>    void insert(iterator position,I first,I last)    {        cout<<"insert()"<<endl;        cout<<typeid(I).name()<<endl;    }};int main(){    int ia[5]={0,1,2,3,4};    vector<int> x;    vector<int>::iterator ite;    x.insert(ite,*ia,*(ia+5));}

运行结果:

[root@localhost stlsource]# ./lconfig8insert()i

    2.6)__STL_LIMITED_DEFAULT_TEMPLATES

    1. 如果编译器不能根据前一个模板参数设定后面的默认模板参数,  
    2. //       则定义__STL_LIMITED_DEFAULT_TEMPLATES
#include<iostream>#include<cstddef>using namespace std;class alloc{};template <typename T,class Alloc=alloc,size_t Bufsiz=0>class deque{public:    deque(){cout<<"deque"<<endl;}};template <typename T,class Sequence=deque<T> >class stack{public:    stack(){ cout<<"stack"<<endl;}private:    Sequence c;//调用deque的构造函数初始化};int main(){    stack<int> x;}

  运行结果:

[root@localhost stlsource]# ./lconfig10 dequestack

      2.7)__STL_NON_TYPE_TMPL_PARAM_BUG 

    1. 如果编译器处理模板函数的non-type模板参数类型推断有困难,  
    2. //       则定义__STL_NON_TYPE_TMPL_PARAM_BUG

 

STL源码剖析—stl_config