日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STL源码剖析—stl_config

發布時間:2023/12/20 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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 _PTHREADScout<<"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_TEMPLATEScout<<"__STL_CLASS_PARTIAL_SPECIALIZATION"<<endl; # endif # ifdef _MEMBER_TEMPLATEScout<<"__STL_MEMBER_TEMPLATES"<<endl; # endif # if !defined(_EXPLICIT_IS_KEYWORD)cout<<"__STL_NEED_EXPLICIT"<<endl; # endif # ifdef __EXCEPTIONScout<<"__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; # endifcout<<"__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; # elsecout<<"__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 __EXCEPTIONScout<<"__STL_USE_EXCEPTIONS"<<endl; # endifcout<<"__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 > 1000cout<<"include <yvals.h>"<<endl; # elsecout<<"__STL_NEED_BOOL"<<endl; # endifcout<<"__STL_NO_DRAND48"<<endl;cout<<"__STL_NEED_TYPENAME"<<endl; # if _MSC_VER < 1100cout<<"__STL_NEED_EXPLICIT"<<endl; # endifcout<<"__STL_NON_TYPE_TMPL_PARAM_BUG"<<endl;cout<<"__SGI_STL_NO_ARROW_OPERATOR"<<endl; # ifdef _CPPUNWINDcout<<"__STL_USE_EXCEPTIONS"<<endl; # endif # ifdef _MTcout<<"__STL_WIN32THREADS"<<endl; # endifcout<<"_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 _CPPUNWINDcout<<"__STL_USE_EXCEPTIONS"<<endl; # endif # ifdef __MT__cout<<"__STL_WIN32THREADS"<<endl; # endifcout<<"__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_TYPENAMEcout<<"define typename"<<endl; # endif# ifdef __STL_NEED_EXPLICITcout<<"define explicit"<<endl; # endif# ifdef __STL_EXPLICIT_FUNCTION_TMPL_ARGScout<<"__STL_NULL_TMPL_ARGS <>"<<endl; # elsecout<<"__STL_NULL_TMPL_ARGS"<<endl; # endif# ifdef __STL_CLASS_PARTIAL_SPECIALIZATIONcout<<"__STL_TEMPLATE_NULL template<>"<<endl; # elsecout<<"__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; # elsecout<<"! __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_EXCEPTIONScout<<"__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; # elsecout<<"! __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; #elsecout<<"__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?

  • 如果編譯器不支持static?members?of?template?classes(模板類靜態成員),??
  • //???????則定義__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=1;template<> int testClass<char>::_data=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 1 2 1 1 2 2 3 3 4 4

    ? ?2.2)__STL_CLASS_PARTIAL_SPECIALIZATION

  • 如果編譯器支持partial?specialization?of?class?templates(局部特殊化的類模板),??
  • //???????則定義__STL_CLASS_PARTIAL_SPECIALIZATION??
  • //???????參考文獻:?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]# ./lconfig5 I,O T*,T* const T*,T*

    ? ??2.3)__STL_FUNCTION_TMPL_PARTIAL_ORDER

  • 如果編譯器支持partial?ordering?of?function?templates(部分排序函數模板),??
  • //???????則定義__STL_FUNCTION_TMPL_PARTIAL_ORDER??
  • //???????參考資料:?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_ORDER template <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 ?內都沒有用到此一常數定義

  • 如果編譯器支持calling?a?function?template?by?providing?its?template??
  • //???????arguments?explicitly(顯式指定調用模板函數的模板參數)?
  • ? ??2.5)__STL_MEMBER_TEMPLATES?

  • 如果編譯器支持template?members?of?classes(類模板成員),??
  • //???????則定義__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]# ./lconfig8 insert() i

    ? ??2.6)__STL_LIMITED_DEFAULT_TEMPLATES

  • 如果編譯器不能根據前一個模板參數設定后面的默認模板參數,??
  • //???????則定義__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 deque stack

      ? ??2.7)__STL_NON_TYPE_TMPL_PARAM_BUG?

  • 如果編譯器處理模板函數的non-type模板參數類型推斷有困難,??
  • //???????則定義__STL_NON_TYPE_TMPL_PARAM_BUG
  • ?

    #include<iostream> #include<cstddef> using namespace std;class alloc{};inline size_t __deque_buf_size(size_t n,size_t sz) {return n!=0?n:(sz<512?size_t(512/sz):size_t(1)); }template <class T,class Ref,class Ptr,size_t Bufsiz> struct __deque_iterator{typedef __deque_iterator<T,T&,T*,Bufsiz> iterator;typedef __deque_iterator<T,const T&,const T*,Bufsiz> const_iterator;static size_t buffer_size() {return __deque_buf_size(Bufsiz,sizeof(T));} };template <class T,class Alloc=alloc,size_t Bufsiz=0> class deque { public:typedef __deque_iterator<T,T&,T*,Bufsiz> iterator; };int main() {cout<<deque<int>::iterator::buffer_size()<<endl;cout<<deque<int,alloc,64>::iterator::buffer_size()<<endl; }

      運行結果:

      

     ? ??2.8)__STL_NULL_TMPL_ARGS(bound friend template friend)

    <stl_config.h>定義__STL_NULL_TMPL_ARGS如下:

    #ifdef __STL_NULL_TMPL_ARGS # define __STL_NULL_TMPL_ARGS <> #else # define __STL_NULL_TMPL_ARGS #endif

      這個組態常量常常出現在類似這樣的場合(class template的friend函數聲明)。

    // in <stl_stack.h> template<class T,class Sequence=deque<T> > class stack{friend bool operator==___STL_NULL_TMPL_ARGS(const stack &,const stack&);friend bool operator< __STL_NULL_TMPL_ARGS(const stack&,const stack&);... };展開后就變成了:template<class T,class Sequence=deque<T> > class stack{friend bool operator== <>(const stack &,const stack&);friend bool operator< <>(const stack&,const stack&);... };

      這種奇特的語法是為了實現所謂的 bound friend templates,也就是說class template的某個具現體(instantiation)與其friend function template的某個具現體有一對一的關系。下面是測試程序:

    #include<iostream> #include<cstddef> using namespace std;class alloc{};template<class T,class Alloc=alloc,size_t BufSiz=0> class deque { public:deque(){cout<<"deque"<<endl;} }; //類模板與友元的一對一關系需要前置聲明 template<class T,class Sequence> class stack;template<class T,class Sequence> bool operator==(const stack<T,Sequence>& x,const stack<T,Sequence>& y);template<class T,class Sequence> bool operator<(const stack<T,Sequence>& x,const stack<T,Sequence>& y);template<class T,class Sequence=deque<T> > class stack {//friend bool operator==<T>(const stack<T>&,const stack<T>&);//friend bool operator< <T>(const stack<T>&,const stack<T>&);//下面的都是等價于上面的//friend bool operator== <T>(const stack&,const stack&);//friend bool operator< <T>(const stack&,const stack&);friend bool operator== <>(const stack&,const stack&);friend bool operator< <>(const stack&,const stack&); public:stack(){cout<<"stack"<<endl;} private:Sequence c; };template<class T,class Sequence> bool operator==(const stack<T,Sequence> &x,const stack<T,Sequence> &y) {return cout<<"operator=="<<'\t'; }template<class T,class Sequence> bool operator<(const stack<T,Sequence> &x,const stack<T,Sequence> &y) {return cout<<"operator<"<<'\t'; }int main() {stack<int> x;stack<int> y;cout<<(x==y)<<endl;cout<<(x<y)<<endl;stack<char> y1; // cout<<(x==y1)<<endl;// cout<<(x<y1)<<endl; }

      運行結果:

    ?

    ? ??2.9)__STL_TEMPLATE_NULL(class template explicit specialization)


    <stl_config.h>定義了一個__STL_TEMPLATE_NULL如下:

    #ifdef __STL_CLASS_PAPTIAL_SPECIALIZATION #define __STL_TEMPLATE_NULL template<> #else #define __STL_TEMPLATE_NULL #endif

      這個組態常量常常出現在類似這樣的場合:

    //in <type_traits.h> template <class type> struct _type_traits {...}; __STL_TEMPLATE_NULL struct _type_traits<char> {};//in <stl_hash_fun.h> template <class key> struct hash{}; __STL_TEMPLATE_NULL struct hash<char> {}; __STL_TEMPLATE_NULL struct hash<unsigned char> {};

      展開后:

    //in <type_traits.h> template <class type> struct _type_traits {...}; template<> struct _type_traits<char> {};//in <stl_hash_fun.h> template <class key> struct hash{}; template<> struct hash<char> {}; template<> struct hash<unsigned char> {};

      這就是所謂的class template explicit specialization。

    下面是一個測試程序:

    #include<iostream> //不能使用 using namespace std 這會將標準庫中的hash引入,然后通不過 using std::cout; using std::endl;//貌似我使用g++編譯,定義為空不能通過 //#define __STL_TEMPLATE_NULL #define __STL_TEMPLATE_NULL template<>template <class key> struct hash {//重載函數調用運算符void operator()(){cout<<"hash<T>"<<endl;} };template<> struct hash<char> {void operator()(){cout<<"hash<char>"<<endl;} };__STL_TEMPLATE_NULL struct hash<unsigned char> {void operator()(){cout<<"hash<unsigned char"<<endl;} };int main() {hash<long> t1;hash<char> t2;hash<unsigned char> t3;t1();//函數對象和函數指針類似,可以作為可調用對象t2();t3(); }

      運行結果:

    ?

    總結

    以上是生活随笔為你收集整理的STL源码剖析—stl_config的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。