一开始看源码剖析首先看到组态很困惑,后来仔细看原来是configuration,也就是配置的意思。STL应该从编译器支持模板的哪些功能看起,毕竟STL就是标准模板库。否则在看源代码的时候就会在#ifdef #endif 等宏中纠结不定。
配置相关
相关的宏都定义在了stl_config.h里面
// Flags:
// * __STL_NO_BOOL: defined if the compiler doesn't have bool as a builtin
// type.
// * __STL_HAS_WCHAR_T: defined if the compier has wchar_t as a builtin type.
// * __STL_NO_DRAND48: defined if the compiler doesn't have the drand48
// function.
// * __STL_STATIC_TEMPLATE_MEMBER_BUG: defined if the compiler can't handle
// static members of template classes.
// * __STL_STATIC_CONST_INIT_BUG: defined if the compiler can't handle a
// constant-initializer in the declaration of a static const data member
// of integer type. (See section 9.4.2, paragraph 4, of the C++ standard.)
// * __STL_CLASS_PARTIAL_SPECIALIZATION: defined if the compiler supports
// partial specialization of template classes.
// * __STL_PARTIAL_SPECIALIZATION_SYNTAX: defined if the compiler
// supports partial specialization syntax for full specialization of
// class templates. (Even if it doesn't actually support partial
// specialization itself.)
// * __STL_FUNCTION_TMPL_PARTIAL_ORDER: defined if the compiler supports
// partial ordering of function templates. (a.k.a partial specialization
// of function templates.)
// * __STL_MEMBER_TEMPLATES: defined if the compiler supports template
// member functions of classes.
// * __STL_MEMBER_TEMPLATE_CLASSES: defined if the compiler supports
// nested classes that are member templates of other classes.
// * __STL_EXPLICIT_FUNCTION_TMPL_ARGS: defined if the compiler
// supports calling a function template by providing its template
// arguments explicitly.
// * __STL_LIMITED_DEFAULT_TEMPLATES: defined if the compiler is unable
// to handle default template parameters that depend on previous template
// parameters.
// * __STL_NON_TYPE_TMPL_PARAM_BUG: defined if the compiler has trouble with
// function template argument deduction for non-type template parameters.
// * __SGI_STL_NO_ARROW_OPERATOR: defined if the compiler is unable
// to support the -> operator for iterators.
// * __STL_DEFAULT_CONSTRUCTOR_BUG: defined if T() does not work properly
// when T is a builtin type.
// * __STL_USE_EXCEPTIONS: defined if the compiler (in the current compilation
// mode) supports exceptions.
// * __STL_USE_NAMESPACES: defined if the compiler has the necessary
// support for namespaces.
// * __STL_NO_EXCEPTION_HEADER: defined if the compiler does not have a
// standard-conforming header <exception>.
// * __STL_NO_BAD_ALLOC: defined if the compiler does not have a <new>
// header, or if <new> does not contain a bad_alloc class. If a bad_alloc
// class exists, it is assumed to be in namespace std.
// * __STL_SGI_THREADS: defined if this is being compiled for an SGI IRIX
// system in multithreaded mode, using native SGI threads instead of
// pthreads.
// * __STL_WIN32THREADS: defined if this is being compiled on a WIN32
// compiler in multithreaded mode.
// * __STL_PTHREADS: defined if we should use portable pthreads
// synchronization.
// * __STL_UITHREADS: defined if we should use UI / solaris / UnixWare threads
// synchronization. UIthreads are similar to pthreads, but are based
// on an earlier version of the Posix threads standard.
// * __STL_LONG_LONG if the compiler has long long and unsigned long long
// types. (They're not in the C++ standard, but they are expected to be
// included in the forthcoming C9X standard.)
// * __STL_THREADS is defined if thread safety is needed.
// * __STL_VOLATILE is deifined to be "volatile" if threads are being
// used, and the empty string otherwise.
// User-settable macros that control compilation:
// * __STL_USE_SGI_ALLOCATORS: if defined, then the STL will use older
// SGI-style allocators, instead of standard-conforming allocators,
// even if the compiler supports all of the language features needed
// for standard-conforming allocators.
// * __STL_NO_NAMESPACES: if defined, don't put the library in namespace
// std, even if the compiler supports namespaces.
// * __STL_NO_RELOPS_NAMESPACE: if defined, don't put the relational
// operator templates (>, <=. >=, !=) in namespace std::rel_ops, even
// if the compiler supports namespaces and partial ordering of
// function templates.
// * __STL_ASSERTIONS: if defined, then enable runtime checking through the
// __stl_assert macro.
// * _PTHREADS: if defined, use Posix threads for multithreading support.
// * _UITHREADS:if defined, use SCO/Solaris/UI threads for multithreading
// support
// * _NOTHREADS: if defined, don't use any multithreading support.
// * __STL_USE_NEW_IOSTREAMS: if defined, then the STL will use new,
// standard-conforming iostreams (e.g. the <iosfwd> header). If not
// defined, the STL will use old cfront-style iostreams (e.g. the
// <iostream.h> header).
// Other macros defined by this file:
// * bool, true, and false, if __STL_NO_BOOL is defined.
// * typename, as a null macro if it's not already a keyword.
// * explicit, as a null macro if it's not already a keyword.
// * namespace-related macros (__STD, __STL_BEGIN_NAMESPACE, etc.)
// * exception-related macros (__STL_TRY, __STL_UNWIND, etc.)
// * __stl_assert, either as a test or as a null macro, depending on
// whether or not __STL_ASSERTIONS is defined.
相比里面根据不同编译器的支持,这一段的注释更加关键,告诉了我们宏分别代表了什么意思。以下敞开介绍以下具体几种配置:
-
__STL_STATIC _TEMPLATE_MEMBER_BUG
查看模板内部是否支持静态变量
-
__STL_CLASS PARTIAL_SPECIALIZATION
是否支持偏特化
-
__STL_FUNCTION_TMPL_PARTIAL_ORDER
书中意思不甚清楚,暂时理解为从template class传到template function
-
__STL_MEMBER_TEMPLATES
类模板里面的成员函数,可以为模板函数
-
__STL_LIMITED_DEFAULT_TEMPLATES
template 参数可以根据前一个template参数而设定
-
__STL_NON_TYPE_TMPL_PARAM_BUG
模板是否可以有非类型参数(常数,基本类型)
-
__STL_NULL_TMPL_ARGS -> <>
bound friend template 就是函数的实体化和类有一一对应的关系
-
__STL_TEMPLATE_NULL (class template explicit specialization)
是否支持全特化
其他可能的问题
临时对象的产生与运用
无名的对象,其实就是相当于把类名称命名成函数本来的名称,然后重载operator()运算符。把函数内容copy到重载中去。
静态常量整数成员在class内部直接初始化
除了int,long和char都属于整数类型,都可以在直接初始化。.
template <typename T>
class testClass{
public:
static const int datai = 0;
static const long datal = 0;
static const char datac = 0;
};
increment/decrement/dereference 操作符
-
i++:表示先做完改次运算,然后在返回
-
++i:表示先加,再返回
//prefix :increment and then fetch ++i
int& operator++()
{
++(this->m_i);
return *this;
}
//postfix :fetch and increment i++
const int operator++(int)
{
int temp = *this;
++(*this);
return temp;
}
前闭后开区间表示法[)
迭代器last的位置是最后一个元素的下一个位置。
这样的好处在于,遍历的条件就变为了if(first == last).而不用在意长度为多少。
function call 操作符(operator())
STL中实现函数一般提供两种版本,一种是一般情况,另一种用于特使情况。尔特是情况则需要用户去指定某种策略。而该策略应该由统一的接口表示。
表示这一组操作可以是函数指针。但是,局部函数无法持有自己的状态,那么就无法达到组件技术中的可适配性。而类可以做到。