操作系統: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?
#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
#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
#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 ?內都沒有用到此一常數定義
? ??2.5)__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
#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?
#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;
}
運行結果:
?
#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的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。