操作系统: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 >= ) && 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__ < || (__GNUC__ == && __GNUC_MINOR__ < )
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__ >= && 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 >
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 <
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 ;
}

运行结果:

[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=; template<>
int testClass<char>::_data=; 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=;
Objc1._data=; cout<<Obji1._data<<endl;
cout<<Obji2._data<<endl;
cout<<Objc1._data<<endl;
cout<<Objc2._data<<endl;
}

运行结果:

[root@localhost stlsource]# ./lconfig3 

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]# ./lconfig5
I,O
T*,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_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_ORDER int 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[]={,,,,};
vector<int> x;
vector<int>::iterator ite;
x.insert(ite,*ia,*(ia+));
}

运行结果:

[root@localhost stlsource]# ./lconfig8
insert()
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
deque
stack

      2.7)__STL_NON_TYPE_TMPL_PARAM_BUG 

    1. 如果编译器处理模板函数的non-type模板参数类型推断有困难,
    2. //       则定义__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();
}

  运行结果:

最新文章

  1. Activity详解生命周期(Android)
  2. http 错误代码表
  3. selenium定位页面元素的一件趣事
  4. 《Getting Started with Storm》章节一 基础
  5. 有趣的数-回文数(Palindrome number)
  6. DDD, MVC &amp; Entity Framework
  7. openldap 安装 配置 使用
  8. mongoDB在windows下基于配置文件的安装和权限配置方式
  9. MFC 学习 之 状态栏的添加
  10. 安装mod_deflate模块启用apache的GZIP压缩
  11. junit测试时,出现java.lang.IllegalStateException: Failed to load ApplicationContext
  12. quick 2.23 它们的定义c++代码lua与总结的一些细节
  13. Nest客户端的基本使用方法
  14. Swift基础之UITextField
  15. RxJS操作符(一)
  16. AJAX请求返回HTTP 400 错误 - 请求无效 (Bad request)
  17. python中Flask模块的使用
  18. webpack环境搭建
  19. Andorid之ActivityManager
  20. ZOJ 2587 Unique Attack(最小割唯一性判断)

热门文章

  1. linux 监控系统缓存和cpu
  2. grunt 合并压缩任务
  3. jQuery API中文文档
  4. 使用appium做自动化时如何切换activity
  5. centos下Elasticsearch数据迁移与备份
  6. NtQuerySystemInformation的使用(提供50余种信息)
  7. 设置Git提交时不用输入用户名和密码
  8. Linux Kernel ‘test_root()’函数本地拒绝服务漏洞
  9. -_-#【JS】isFinite
  10. awk合并文件一例