2 STL的程式設計範式
OOP(Object-Oriented Programming):面向對象 資料和操作在同一個類;OOP企圖将datas和methods關聯在一起
template<class T, class Alloc = alloc>
class list{
...
void sort();
}
GP(Generic Programming):泛型程式設計 datas和methods分隔開,即algorithm和contains分隔開,通過iterator互動。
template<typename _RandomAccessIterator>
inline void sort(_RandomAccessIterator __first, _RandomAccessIterator __end)
STL采用GP的原因:
- Containers和Algorithms團隊刻個字閉門造車,Iterators團隊溝通。
- Algorithms通過Iterators确定操作範圍,并通過Iterators取用Containers元素。
例子:
有算法(Algorithms)如下:
template<class T>
inline const min T&(const T& a, const T& b){
return b < a ? b : a;
}
如果要對一個自定義類進行大小比較,則可以重載<,或者寫個Compare函數。這樣,算法就有了其通用性,而無需關心容器是什麼。
泛化、特化、偏特化
特化即特殊化,即設計者認為對于制定類型,使用特定版本更好。
全特化就是限定死模闆實作的具體類型。
偏特化就是如果這個模闆有多個類型,那麼隻限定其中的一部分。
優先級:全特化類>偏特化類>主版本模闆類
//泛化
Template <class type>
Struct __type_traits{typedef __true_type this_dummy_member_must_be_first; };
//特化1
Template < >
Struct __type_traits<int>{typedef __true_type this_dummy_member_must_be_first; };
//特化2
Template < >
Struct __type_traits<double>{typedef __true_type this_dummy_member_must_be_first; };
//__type_traits<FOO>:: this_dummy_member_must_be_first; 使用的是泛化的内容
//泛化
Template <class T, class Alloc = alloc>
Class vecor{};
//偏特化(個數偏特化,第一個特化,第二個不特化)
Template <class Alloc>
Class vector<bool, Alloc>{};
//泛化
Template <class Iterator>
Struct iterator_traits {};
//偏特化1(範圍偏特化,隻能是傳入指針)
Template <class T>
Struct iterator_traits<T*>{};
//偏特化2
Template <class T>
Struct iterator_traits<const T*>{};
為什麼list不能使用::sort函數
list底層資料結構為連結清單,不支援随機通路(random access),是以list這個Containers中,有自帶的sort方法。
::sort接口為:
sort(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp)
{
typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
_VSTD::__sort<_Comp_ref>(__first, __last, _Comp_ref(__comp));
}
list.sort為,可以看到為連結清單的歸并排序:
template <class _Tp, class _Alloc>
template <class _Comp>
typename list<_Tp, _Alloc>::iterator
list<_Tp, _Alloc>::__sort(iterator __f1, iterator __e2, size_type __n, _Comp& __comp)
{
switch (__n)
{
case 0:
case 1:
return __f1;
case 2:
if (__comp(*--__e2, *__f1))
{
__link_pointer __f = __e2.__ptr_;
base::__unlink_nodes(__f, __f);
__link_nodes(__f1.__ptr_, __f, __f);
return __e2;
}
return __f1;
}
size_type __n2 = __n / 2;
iterator __e1 = _VSTD::next(__f1, __n2);
iterator __r = __f1 = __sort(__f1, __e1, __n2, __comp);
iterator __f2 = __e1 = __sort(__e1, __e2, __n - __n2, __comp);
if (__comp(*__f2, *__f1))
{
iterator __m2 = _VSTD::next(__f2);
for (; __m2 != __e2 && __comp(*__m2, *__f1); ++__m2)
;
__link_pointer __f = __f2.__ptr_;
__link_pointer __l = __m2.__ptr_->__prev_;
__r = __f2;
__e1 = __f2 = __m2;
base::__unlink_nodes(__f, __l);
__m2 = _VSTD::next(__f1);
__link_nodes(__f1.__ptr_, __f, __l);
__f1 = __m2;
}
else
++__f1;
while (__f1 != __e1 && __f2 != __e2)
{
if (__comp(*__f2, *__f1))
{
iterator __m2 = _VSTD::next(__f2);
for (; __m2 != __e2 && __comp(*__m2, *__f1); ++__m2)
;
__link_pointer __f = __f2.__ptr_;
__link_pointer __l = __m2.__ptr_->__prev_;
if (__e1 == __f2)
__e1 = __m2;
__f2 = __m2;
base::__unlink_nodes(__f, __l);
__m2 = _VSTD::next(__f1);
__link_nodes(__f1.__ptr_, __f, __l);
__f1 = __m2;
}
else
++__f1;
}
return __r;
}