什么时机下最合适选择那种容器,依据:
1 元素多寡
2 元素构造复杂度
3 元素存取行为特性
转载出处:http://hi.baidu.com/walkandsing Matt Austern在Generic Programming and the STL中提出了Concept、Model、Refinement的概念,实际上是换汤不换药,就是类似于Class、Object、SubClass的概念,只不过是在Template的语义下面解释的而已,唯一的差别就是在Template下,类型是implicit的,对类型的要求比较松散。而所谓的Concept Checks就是类似于assert的东西,专业点讲就是static assertion,就是利用编译器在Compiling的时候的检查来做一些检查,例如: #define STATIC_ASSERTION(_cond,_name) typedef char STATIC_ASSERT_FAILED_ ## _name[(_cond)?1:-1] STL中和概念检查有关的文件有:concept_checks.h、container_concepts.h、sequence_concepts.h和assoc_container_concepts.h。 先从concept_checks.h开始,这个文件定义了一些基础的概念和iterator的概念,主要的接口是: #define __STL_CLASS_REQUIRES(__type_var, __concept): 检查__type_var是否满足__concept,当前定义的概念有:_Allocator、_Assignable、_DefaultConstructible、_EqualityComparable、_LessThanComparable、_TrivialIterator、_InputIterator、_OutputIterator、_ForwardIterator、_BidirectionalIterator、_RandomAccessIterator、_Mutable_TrivialIterator、_Mutable_ForwardIterator、_Mutable_BidirectionalIterator、_Mutable_RandomAccessIterator。 #define __STL_CONVERTIBLE(__type_x, __type_y) 检查类型_x能否转换为类型_y。 #define __STL_CLASS_REQUIRES_SAME_TYPE(__type_x, __type_y): 检查类型_x能否和类型_y为同一个类型。 #define __STL_CLASS_GENERATOR_CHECK(__func, __ret): 用于在算法generate和generate_n中用来检查generator合法性。 #define __STL_CLASS_UNARY_FUNCTION_CHECK(__func, __ret, __arg): 检查__func的参数为__arg类型,返回值为__ret类型。 #define __STL_CLASS_BINARY_FUNCTION_CHECK(__func, __ret, __first, __second): 检查__func的参数为__first和__second类型,返回值为__ret类型。 #define __STL_CLASS_REQUIRES_BINARY_OP(__opname, __ret, __first, __second): 检查__ret __opname(__first, __second)是否合法。
在看这些接口的具体实现前,还需要了解一点他们的实现细节,在concept_checks.h中定义了一个类_STL_ERROR,里面定义了一些static模板函数,这些方法组成了static assertion的最小单元: template <class _Type> static _Type __default_constructor_requirement_violation(_Type) { return _Type(); } template <class _Type> static _Type __assignment_operator_requirement_violation(_Type __a) { __a = __a; return __a; } ….(省略) 这些方法都是利用一些简单的表达式使得编译器来判断__Type是否支持某一种操作,当其不支持的时候,compiler就会报错,函数名将被打印出来,这样用户就能知道出错的原因了。还有一些模板方法是用来检测类型里是否定义了某些typedef,如: template <class _Iter> struct __value_type_type_definition_requirement_violation { typedef typename __STD::iterator_traits<_Iter>::value_type value_type; };
template <class _Iter> struct __difference_type_type_definition_requirement_violation { typedef typename __STD::iterator_traits<_Iter>::difference_type difference_type; }; …. 然后基于这些atomic的static assertion组合出了一些概念: template <class _Type> struct _Assignable_concept_specification { static void _Assignable_requirement_violation(_Type __a) { _STL_ERROR::__assignment_operator_requirement_violation(__a); _STL_ERROR::__copy_constructor_requirement_violation(__a); _STL_ERROR::__const_parameter_required_for_copy_constructor(__a,__a); _STL_ERROR::__const_parameter_required_for_assignment_operator(__a,__a); } }; template <class _TrivialIterator> struct _TrivialIterator_concept_specification { static void _TrivialIterator_requirement_violation(_TrivialIterator __i) { typedef typename __value_type_type_definition_requirement_violation<_TrivialIterator>:: value_type __T; // Refinement of Assignable _Assignable_concept_specification<_TrivialIterator>:: _Assignable_requirement_violation(__i); // Refinement of DefaultConstructible _DefaultConstructible_concept_specification<_TrivialIterator>:: _DefaultConstructible_requirement_violation(__i); // Refinement of EqualityComparable _EqualityComparable_concept_specification<_TrivialIterator>:: _EqualityComparable_requirement_violation(__i); // Valid Expressions _STL_ERROR::__dereference_operator_requirement_violation(__i); } }; template <class _InputIterator> struct _InputIterator_concept_specification { static void _InputIterator_requirement_violation(_InputIterator __i) { // Refinement of TrivialIterator _TrivialIterator_concept_specification<_InputIterator>:: _TrivialIterator_requirement_violation(__i); // Associated Types __difference_type_type_definition_requirement_violation<_InputIterator>(); __reference_type_definition_requirement_violation<_InputIterator>(); __pointer_type_definition_requirement_violation<_InputIterator>(); __iterator_category_type_definition_requirement_violation<_InputIterator>(); // Valid Expressions _STL_ERROR::__preincrement_operator_requirement_violation(__i); _STL_ERROR::__postincrement_operator_requirement_violation(__i); } }; …. 到目前为止,这些函数都是些函数调用,怎么达到在编译的时候判断的目的呢?谜底就在接口定义中,以__STL_REQUIRES为例,它的定义为: #define __STL_REQUIRES(__type_var, __concept) / do { / void (*__x)( __type_var ) = __concept##_concept_specification< __type_var >/ ::__concept##_requirement_violation; __x = __x; } while (0)
比如在很多算法的开头都有检查: __STL_REQUIRES(_InputIter, _InputIterator);
评论:定义函数指针不会触发模板实例化,指针赋值使编译器会静态检查模板内部实现。 这时相当于在block里定义了一个函数指针__x,而__x=__x将触发模板的实例化,这时编译器开始对_InputIterator_concept_specification::_InputIterator_requirement_violation中的所有的static assertion进行检查,但又不会调用这些函数,这样只会在编译期间会产生开销。 其他的接口定义也都类似,值得一提的还有__STL_CONVERTIBLE和__STL_REQUIRES_SAME_TYPE,实际上在Modern C++ Design中有提到这两个模板,但我发现在STL中这两个模板的实现更加简洁。 template <class _TypeX, class _TypeY> struct _STL_CONVERT_ERROR { static void __type_X_is_not_convertible_to_type_Y(_TypeX __x, _TypeY) { _TypeY __y = __x; __sink_unused_warning(__y); } }; #define __STL_CONVERTIBLE(__type_x, __type_y) / do { / void (*__x)( __type_x , __type_y ) = _STL_CONVERT_ERROR< __type_x , / __type_y >::__type_X_is_not_convertible_to_type_Y; / __x = __x; } while (0) 很简单,就是通过赋值来判断的。 template <class _Type> struct __check_equal { };
template <class _TypeX, class _TypeY> struct _STL_SAME_TYPE_ERROR { static void __type_X_not_same_as_type_Y(_TypeX , _TypeY ) { __check_equal<_TypeX> t1 = __check_equal<_TypeY>(); } }; #define __STL_REQUIRES_SAME_TYPE(__type_x, __type_y) / do { / void (*__x)( __type_x , __type_y ) = _STL_SAME_TYPE_ERROR< __type_x, / __type_y >::__type_X_not_same_as_type_Y; / __x = __x; } while (0) 这个稍微麻烦一点,虽然也是通过赋值来判断但引入了一个空模板__check_equal,当_TypeX和_TypeY类型不同的时候,__check_equal<_TypeX>和__check_equal<_TypeY>肯定不同,即使_TypeX和_TypeY是convertiable的,__check_equal<_TypeX>和__check_equal<_TypeY>的赋值也是非法的。 在container_concepts.h和sequence_concepts.h中的方法和上述类似,在此不再累述。 |