Chinaunix首页 | 论坛 | 博客
  • 博客访问: 6467091
  • 博文数量: 579
  • 博客积分: 1548
  • 博客等级: 上尉
  • 技术积分: 16635
  • 用 户 组: 普通用户
  • 注册时间: 2012-12-12 15:29
个人简介

http://www.csdn.net/ http://www.arm.com/zh/ https://www.kernel.org/ http://www.linuxpk.com/ http://www.51develop.net/ http://linux.chinaitlab.com/ http://www.embeddedlinux.org.cn http://bbs.pediy.com/

文章分类

全部博文(579)

文章存档

2018年(18)

2015年(91)

2014年(159)

2013年(231)

2012年(80)

分类: C/C++

2013-12-11 20:40:29

操作系统:ubuntu10.04
STL源码版本:2.91


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

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


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

点击(此处)折叠或打开

  1. #include <iostream>
  2. #include <stdio.h>
  3. using namespace std;


  4. void    test(void)
  5. {
  6. #ifdef _PTHREADS
  7.     cout<<"define __STL_PTHREADS"<<endl;
  8. #endif

  9. # if defined(__sgi) && !defined(__GNUC__)
  10.     cout<<"__sgi begin"<<endl;
  11. # if !defined(_BOOL)
  12.         cout<<"__STL_NEED_BOOL"<<endl;
  13. # endif
  14. # if !defined(_TYPENAME_IS_KEYWORD)
  15.          cout<<"__STL_NEED_TYPENAME"<<endl;
  16. # endif
  17. # ifdef _PARTIAL_SPECIALIZATION_OF_CLASS_TEMPLATES
  18.         cout<<"__STL_CLASS_PARTIAL_SPECIALIZATION"<<endl;
  19. # endif
  20. # ifdef _MEMBER_TEMPLATES
  21.         cout<<"__STL_MEMBER_TEMPLATES"<<endl;
  22. # endif
  23. # if !defined(_EXPLICIT_IS_KEYWORD)
  24.         cout<<"__STL_NEED_EXPLICIT"<<endl;
  25. # endif
  26. # ifdef __EXCEPTIONS
  27.         cout<<"__STL_USE_EXCEPTIONS"<<endl;
  28. # endif
  29. # if (_COMPILER_VERSION >= 721) && defined(_NAMESPACES)
  30.         cout<<"__STL_USE_NAMESPACES"<<endl;
  31. # endif
  32. # if !defined(_NOTHREADS) && !defined(__STL_PTHREADS)
  33.         cout<<"__STL_SGI_THREADS"<<endl;
  34. # endif
  35.     cout<<"__sgi end"<<endl<<endl;
  36. # endif

  37. # ifdef __GNUC__
  38.     cout<<"__GNUC__ begin"<<endl;
  39. # include <_G_config.h>
  40. # if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 8)
  41.         cout<<"__STL_STATIC_TEMPLATE_MEMBER_BUG"<<endl;
  42.         cout<<"__STL_NEED_TYPENAME"<<endl;
  43.         cout<<"__STL_NEED_EXPLICIT"<<endl;
  44. # else
  45.         cout<<"__STL_CLASS_PARTIAL_SPECIALIZATION"<<endl;
  46.         cout<<"__STL_FUNCTION_TMPL_PARTIAL_ORDER"<<endl;
  47.         cout<<"__STL_EXPLICIT_FUNCTION_TMPL_ARGS"<<endl;
  48.         cout<<"__STL_MEMBER_TEMPLATES"<<endl;
  49. # endif
  50.     /* glibc pre 2.0 is very buggy. We have to disable thread for it.
  51.        It should be upgraded to glibc 2.0 or later. */
  52. # if !defined(_NOTHREADS) && __GLIBC__ >= 2 && defined(_G_USING_THUNKS)
  53.         cout<<"__STL_PTHREADS"<<endl;
  54. # endif
  55. # ifdef __EXCEPTIONS
  56.         cout<<"__STL_USE_EXCEPTIONS"<<endl;
  57. # endif
  58.     cout<<"__GNUC__ end"<<endl<<endl;
  59. # endif

  60. # if defined(__SUNPRO_CC)
  61.     cout<<"__SUNPRO_CC begin"<<endl;
  62.     cout<<"__STL_NEED_BOOL"<<endl;
  63.     cout<<"__STL_NEED_TYPENAME"<<endl;
  64.     cout<<"__STL_NEED_EXPLICIT"<<endl;
  65.     cout<<"__STL_USE_EXCEPTIONS"<<endl;
  66.     cout<<"__SUNPRO_CC end"<<endl<<endl;
  67. # endif

  68. # if defined(__COMO__)
  69.     cout<<"__COMO__ begin"<<endl;
  70.     cout<<"__STL_MEMBER_TEMPLATES"<<endl;
  71.     cout<<"__STL_CLASS_PARTIAL_SPECIALIZATION"<<endl;
  72.     cout<<"__STL_USE_EXCEPTIONS"<<endl;
  73.     cout<<"__STL_USE_NAMESPACES"<<endl;
  74.     cout<<"__COMO__ end"<<endl<<endl;
  75. # endif

  76. # if defined(_MSC_VER)
  77. cout<<"_MSC_VER begin"<<endl;
  78. # if _MSC_VER > 1000
  79.         cout<<"include "<<endl;
  80. # else
  81.         cout<<"__STL_NEED_BOOL"<<endl;
  82. # endif
  83.         cout<<"__STL_NO_DRAND48"<<endl;
  84.         cout<<"__STL_NEED_TYPENAME"<<endl;
  85. # if _MSC_VER < 1100
  86.         cout<<"__STL_NEED_EXPLICIT"<<endl;
  87. # endif
  88.         cout<<"__STL_NON_TYPE_TMPL_PARAM_BUG"<<endl;
  89.         cout<<"__SGI_STL_NO_ARROW_OPERATOR"<<endl;
  90. # ifdef _CPPUNWIND
  91.         cout<<"__STL_USE_EXCEPTIONS"<<endl;
  92. # endif
  93. # ifdef _MT
  94.         cout<<"__STL_WIN32THREADS"<<endl;
  95. # endif
  96.     cout<<"_MSC_VER end"<<endl<<endl;
  97. # endif

  98. # if defined(__BORLANDC__)
  99.     cout<<"__BORLANDC__ begin"<<endl;
  100.     cout<<"__STL_NO_DRAND48"<<endl;
  101.     cout<<"__STL_NEED_TYPENAME"<<endl;
  102.     cout<<"__STL_LIMITED_DEFAULT_TEMPLATES"<<endl;
  103.     cout<<"__SGI_STL_NO_ARROW_OPERATOR"<<endl;
  104.     cout<<"__STL_NON_TYPE_TMPL_PARAM_BUG"<<endl;
  105. # ifdef _CPPUNWIND
  106.         cout<<"__STL_USE_EXCEPTIONS"<<endl;
  107. # endif
  108. # ifdef __MT__
  109.         cout<<"__STL_WIN32THREADS"<<endl;
  110. # endif
  111.     cout<<"__BORLANDC__ end"<<endl<<endl;
  112. # endif


  113. # if defined(__STL_NEED_BOOL)
  114.     cout<<"__STL_NEED_BOOL begin"<<endl;
  115.     cout<<"typedef int bool;"<<endl;
  116.     cout<<"define true 1"<<endl;
  117.     cout<<"define false 0"<<endl;
  118.     cout<<"__STL_NEED_BOOL end"<<endl<<endl;
  119. # endif

  120. # ifdef __STL_NEED_TYPENAME
  121.     cout<<"define typename"<<endl;
  122. # endif

  123. # ifdef __STL_NEED_EXPLICIT
  124.     cout<<"define explicit"<<endl;
  125. # endif

  126. # ifdef __STL_EXPLICIT_FUNCTION_TMPL_ARGS
  127.     cout<<"__STL_NULL_TMPL_ARGS <>"<<endl;
  128. # else
  129.     cout<<"__STL_NULL_TMPL_ARGS"<<endl;
  130. # endif

  131. # ifdef __STL_CLASS_PARTIAL_SPECIALIZATION
  132.     cout<<"__STL_TEMPLATE_NULL template<>"<<endl;
  133. # else
  134.     cout<<"__STL_TEMPLATE_NULL"<<endl;
  135. # endif

  136. // __STL_NO_NAMESPACES is a hook so that users can disable namespaces
  137. // without having to edit library headers.
  138. # if defined(__STL_USE_NAMESPACES) && !defined(__STL_NO_NAMESPACES)
  139.     cout<<"__STL_USE_NAMESPACES begin"<<endl;
  140.     cout<<"__STD std"<<endl;
  141.     cout<<"__STL_BEGIN_NAMESPACE namespace std {"<<endl;
  142.     cout<<"__STL_END_NAMESPACE }"<<endl;
  143.     cout<<"__STL_USE_NAMESPACE_FOR_RELOPS"<<endl;
  144.     cout<<"__STL_BEGIN_RELOPS_NAMESPACE namespace std {"<<endl;
  145.     cout<<"__STL_END_RELOPS_NAMESPACE }"<<endl;
  146.     cout<<"__STD_RELOPS std"<<endl;
  147.     cout<<"__STL_USE_NAMESPACES end"<<endl<<endl;
  148. # else
  149.     cout<<"! __STL_USE_NAMESPACES begin"<<endl;
  150.     cout<<"__STD "<<endl;
  151.     cout<<"__STL_BEGIN_NAMESPACE "<<endl;
  152.     cout<<"__STL_END_NAMESPACE "<<endl;
  153.     cout<<"__STL_USE_NAMESPACE_FOR_RELOPS"<<endl;
  154.     cout<<"__STL_BEGIN_RELOPS_NAMESPACE "<<endl;
  155.     cout<<"__STL_END_RELOPS_NAMESPACE "<<endl;
  156.     cout<<"__STD_RELOPS "<<endl;
  157.     cout<<"! __STL_USE_NAMESPACES end"<<endl<<endl;
  158. # endif

  159. # ifdef __STL_USE_EXCEPTIONS
  160.     cout<<"__STL_USE_EXCEPTIONS begin"<<endl;
  161.     cout<<"__STL_TRY try"<<endl;
  162.     cout<<"__STL_CATCH_ALL catch(...)"<<endl;
  163.     cout<<"__STL_RETHROW throw"<<endl;
  164.     cout<<"__STL_NOTHROW throw()"<<endl;
  165.     cout<<"__STL_UNWIND(action) catch(...) { action; throw; }"<<endl;
  166.     cout<<"__STL_USE_EXCEPTIONS end"<<endl<<endl;
  167. # else
  168.     cout<<"! __STL_USE_EXCEPTIONS begin"<<endl;
  169.     cout<<"__STL_TRY "<<endl;
  170.     cout<<"__STL_CATCH_ALL if (false)"<<endl;
  171.     cout<<"__STL_RETHROW "<<endl;
  172.     cout<<"__STL_NOTHROW "<<endl;
  173.     cout<<"__STL_UNWIND(action) "<<endl;
  174.     cout<<"! __STL_USE_EXCEPTIONS end"<<endl<<endl;
  175. # endif

  176. #ifdef __STL_ASSERTIONS
  177. # include <stdio.h>
  178.     cout<<"__stl_assert(expr) \
  179.     if (!(expr)) { fprintf(stderr, \"%s:%d STL assertion failure: %s\n\", \
  180.              __FILE__, __LINE__, # expr); abort(); }"<<endl;
  181. #else
  182.     cout<<"__stl_assert(expr)"<<endl;
  183. #endif


  184. }



  185. int main(void)
  186. {
  187.     test();

  188.     return 0;
  189. }

    运行结果:
    


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

点击(此处)折叠或打开

  1. #ifndef __STL_CONFIG_H
  2. # define __STL_CONFIG_H


  3. # ifdef __GNUC__
  4. # include <_G_config.h>
  5. # define __STL_CLASS_PARTIAL_SPECIALIZATION
  6. # define __STL_FUNCTION_TMPL_PARTIAL_ORDER
  7. # define __STL_EXPLICIT_FUNCTION_TMPL_ARGS
  8. # define __STL_MEMBER_TEMPLATES
  9. # define __STL_PTHREADS
  10. # define __STL_USE_EXCEPTIONS
  11. # endif


  12. # define __STL_NULL_TMPL_ARGS
  13. # define __STL_TEMPLATE_NULL


  14. # define __STD
  15. # define __STL_BEGIN_NAMESPACE
  16. # define __STL_END_NAMESPACE
  17. # undef __STL_USE_NAMESPACE_FOR_RELOPS
  18. # define __STL_BEGIN_RELOPS_NAMESPACE
  19. # define __STL_END_RELOPS_NAMESPACE
  20. # define __STD_RELOPS


  21. # define __STL_TRY
  22. # define __STL_CATCH_ALL if (false)
  23. # define __STL_RETHROW
  24. # define __STL_NOTHROW
  25. # define __STL_UNWIND(action)


  26. # define __stl_assert(expr)

  27. #endif /* __STL_CONFIG_H */

  28. // Local Variables:
  29. // mode:C++
  30. // End:


2,对stl_config.h中的宏的详解
    2.1)__STL_STATIC_TEMPLATE_MEMBER_BUG 
  1. 如果编译器不支持static members of template classes(模板类静态成员),  
  2. //       则定义__STL_STATIC_TEMPLATE_MEMBER_BUG 

点击(此处)折叠或打开

  1. #include <iostream>
  2. using namespace std;
  3.   
  4. template <typename T>
  5. class testclass
  6. {
  7. public:
  8.   static int _data;
  9. };
  10.   
  11. template<> int testclass<int>::_data = 1;
  12. template<> int testclass<char>::_data = 2;
  13.   
  14. int main()
  15. {
  16.   cout<<testclass<int>::_data<<" "<<&testclass<int>::_data<<endl;
  17.   cout<<testclass<char>::_data<<" "<<&testclass<char>::_data<<endl;
  18.   
  19.   testclass<int> obji1, obji2;
  20.   testclass<char> objc1, objc2;
  21.   
  22.   cout<<obji1._data<<" "<<&obji1._data<<endl;
  23.   cout<<obji2._data<<" "<<&obji2._data<<endl;
  24.   cout<<objc1._data<<" "<<&objc1._data<<endl;
  25.   cout<<objc2._data<<" "<<&objc2._data<<endl;
  26.   
  27.   obji1._data = 3;
  28.   objc2._data = 4;
  29.     
  30.   cout<<obji1._data<<" "<<&obji1._data<<endl;
  31.   cout<<obji2._data<<" "<<&obji2._data<<endl;
  32.   cout<<objc1._data<<" "<<&objc1._data<<endl;
  33.   cout<<objc2._data<<" "<<&objc2._data<<endl;
  34.   
  35.   return 1;
  36. }




    2.2)__STL_CLASS_PARTIAL_SPECIALIZATION
  1. 如果编译器支持partial specialization of class templates(局部特殊化的类模板),  
  2. //       则定义__STL_CLASS_PARTIAL_SPECIALIZATION  
  3. //       参考文献: (v=VS.71).aspx 

点击(此处)折叠或打开

  1. #include <iostream>
  2. using namespace std;
  3.   
  4. template <class I, class O>
  5. struct testClass
  6. {
  7.   testClass()
  8.   {
  9.     cout<<"I, O"<<endl;
  10.   }
  11. };
  12.   
  13. template <class T>
  14. struct testClass<T*, T*>
  15. {
  16.   testClass()
  17.   {
  18.     cout<<"T*,T*"<<endl;
  19.   }
  20. };
  21.   
  22. template <class T>
  23. struct testClass<const T*, T*>
  24. {
  25.   testClass()
  26.   {
  27.     cout<<"const T*, T*"<<endl;
  28.   }
  29. };
  30.   
  31. int main()
  32. {
  33.   testClass<int, char> obj1;
  34.   testClass<int*, int*> obj2;
  35.   testClass<const int*, int*> obj3;
  36.   return 1;
  37. }



    2.3)__STL_FUNCTION_TMPL_PARTIAL_ORDER
  1. 如果编译器支持partial ordering of function templates(部分排序函数模板),  
  2. //       则定义__STL_FUNCTION_TMPL_PARTIAL_ORDER  
  3. //       参考资料:  




    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 

点击(此处)折叠或打开

  1. #include <iostream> 
  2. using namespace std; 
  3.   
  4. class alloc 
  5. { 
  6. }; 
  7.   
  8. template <class T, class Alloc = alloc> 
  9. class vector 
  10. { 
  11. public: 
  12.   typedef T value_type; 
  13.   typedef value_type* iterator; 
  14.   
  15.   template <class I> 
  16.   void insert(iterator position, I first, I last) 
  17.   { 
  18.     cout<<"insert()"<<endl; 
  19.   } 
  20. }; 
  21.   
  22. int main() 
  23. { 
  24.   int ia[5] = {0,1,2,3,4}; 
  25.     
  26.   cout<<*ia<<endl; 
  27.   cout<<*(ia+4)<<endl; 
  28.     
  29.   vector<int> x; 
  30.   vector<int>::iterator ite = NULL; 
  31.   x.insert(ite, ia, ia+4); 
  32.   return 1; 
  33. }



    2.6)__STL_LIMITED_DEFAULT_TEMPLATES
  1. 如果编译器不能根据前一个模板参数设定后面的默认模板参数,  
  2. //       则定义__STL_LIMITED_DEFAULT_TEMPLATES

点击(此处)折叠或打开

  1. //测试template 参数可否根据前一个template参数而设定默认值
  2. #include <iostream>
  3. #include <cstddef>
  4.   
  5. using namespace std;
  6.   
  7. class alloc
  8. {
  9. };
  10.   
  11. template <class T, class Alloc = alloc, size_t BufSiz = 0>
  12. class deque
  13. {
  14. public:
  15.   deque()
  16.   {
  17.     cout<<"deque"<<endl;
  18.   }
  19. };
  20.   
  21. template <class T, class Sequence = deque<T> >
  22. class stack
  23. {
  24. public:
  25.   stack()
  26.   {
  27.     cout<<"stack"<<endl;
  28.   }
  29.   
  30. private:
  31.   Sequence c;
  32. };
  33.   
  34. int main()
  35. {
  36.   stack<int> x;
  37. }




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

点击(此处)折叠或打开

  1. //测试class template 可否拥有non-type template参数
  2. #include <iostream>
  3. #include <cstddef>
  4. using namespace std;
  5.   
  6. class alloc
  7. {
  8. };
  9.   
  10. inline size_t __deque_buf_size(size_t n, size_t sz)
  11. {
  12.   return n != 0 ? n : (sz < 512 ? size_t(512/sz) : size_t(1));
  13. }
  14.   
  15. template <class T, class Ref, class Ptr, size_t BufSiz>
  16. struct __deque_iterator
  17. {
  18.   typedef __deque_iterator<T, T&, T*, BufSiz> iterator;
  19.   typedef __deque_iterator<T, const T&, const T*, BufSiz> const_iterator;
  20.   static size_t buffer_size()
  21.   {
  22.     return __deque_buf_size(BufSiz, sizeof(T));
  23.   }
  24. };
  25.   
  26. template <class T, class Alloc = alloc, size_t BufSiz = 0>
  27. class deque
  28. {
  29. public:
  30.   typedef __deque_iterator<T, T&, T*, BufSiz> iterator;
  31. };
  32.   
  33. int main()
  34. {
  35.   cout<<deque<int>::iterator::buffer_size()<<endl;
  36.   cout<<deque<int,alloc,64>::iterator::buffer_size()<<endl;
  37.   return 1;
  38. }






参考文献:
1,《STL源码剖析》
2,http://blog.csdn.net/segen_jaa/article/details/7930349




阅读(4970) | 评论(1) | 转发(1) |
给主人留下些什么吧!~~

CU博客助理2014-03-10 16:37:59

专家点评:学习研究源码是一个枯燥、困难的事情,不但需要耐力,还要有好方法。文章中博主通过一个实例给出答案。
要找到切入点,同时也看出了博主的耐心,文章中重视实践,建议要多些评论和文字性描述,这样就更好了。
学习、探索源码会能大大调高技术水平,忘博主继续努力!
(感谢您参与“原创博文评选”获奖结果即将公布)