#ifndef KNIFE_ALGOBASE_H #define KNIFE_ALGOBASE_H // 这个头文件看似是由一个个基础函数构成的算法库 // 但其实这些算法大部分都是基于iterator这个概念的,即 // 基于iterator的相关全局基础方法,使iterator在被使用 // 的时候更加得心应手;这些方法包括: // iter_swap(); // distance(); advance();这几个在3.0版本后被改至iterator.h中了 // swap(), max(), min(); 这几个不是基于iterator的 // copy(); mismatch(); #include "config.h" #include "iterator.h" #include "knifeio.h" #include "type_traits.h" #include <string.h> // use memmove() in it _STL_NAMESPACE_BEGIN // The name 1 2 implicit a kind of squence, so we use name a b // And indeed we do need a T pointer to init type T implicitly // Cause we can NOT use function or other expression in init type T explicit template <typename InputIterator_a, typename InputIterator_b, typename T> inline void _iter_swap(InputIterator_a a, InputIterator_b b, T*) { T tmp = *a; *a = *b; *b = tmp; } // When we need the thing that iterator point to we should use *a // and when we need the pointer point to the thing // we should use &(*a); template <typename InputIterator_a, typename InputIterator_b> inline void iter_swap(InputIterator_a a, InputIterator_b b) { _iter_swap(a, b, &(*a)); } template <typename T> inline void swap(T& a, T& b) { T tmp = a; a = b; b = tmp; } template <typename T> inline const T& min(const T& a, const T& b) { return (a < b) ? a : b; } template <typename T> inline const T& max(const T& a, const T& b) { return (b < a) ? a : b; } // SGI_STL_203的实现逻辑略微有点奇怪,他将comp(a, b) // 与 b < a等同了,而且并没有使用这个函数的地方,所以 // 我在这里是做了修改的,comp(a, b)应该在a > b时返回true // 在a < b时返回false template <typename T, typename Compare> inline const T& min(const T& a, const T& b, Compare comp) { return comp(a, b) ? b : a; } template <typename T, typename Compare> inline const T& max(const T& a, const T& b, Compare comp) { return comp(a, b) ? a : b; } // 这是描述两个iterator之间的距离的函数 template <typename RandomAccessIterator, typename Distance> inline void _distance(RandomAccessIterator a, RandomAccessIterator b, Distance& dis, random_access_iterator_tag) { dis += b - a; // 注意,这里是在原值基础上加上距离,并不是赋值 } template <typename InputIterator, typename Distance> inline void _distance(InputIterator a, InputIterator b, Distance& dis, input_iterator_tag) { while (a != b) { ++a; ++dis; } // 在前++和后++中,前++是优先实现的,所以优先使用前++ } template <typename InputIterator, typename Distance> inline void distance(InputIterator a, InputIterator b, Distance& distance) { _distance(a, b, distance, iterator_category(a)); } // 由于iterator_category()返回的是临时对象 // 所以不能使用诸如random_access_iterator_tag& // 这样的参数来区分不同的iterator,必须使用random_access_iterator_tag template <typename RandomAccessIterator> inline typename iterator_traits<RandomAccessIterator>::difference_type _distance(RandomAccessIterator a, RandomAccessIterator b, random_access_iterator_tag) { return b - a; } template <typename InputIterator> inline typename iterator_traits<InputIterator>::difference_type _distance(InputIterator a, InputIterator b, input_iterator_tag) { typename iterator_traits<InputIterator>::difference_type dis(0); while (b != a) { ++a; ++dis; } return dis; } template <typename InputIterator> inline typename iterator_traits<InputIterator>::difference_type distance(InputIterator a, InputIterator b) { return _distance(a, b, iterator_category(a)); } // Distance类型被要求支持两个--操作,能转换为bool型 template <typename InputIterator, typename Distance> inline void _advance(InputIterator& i, Distance n, input_iterator_tag) { // 在SGI_STL 2.03是这样的:while (n--) ++i; // 那么当n为负的时候这里是处理不了的,但用户并没有被通知 // 略有不恰当;而且不能要求一个distance一定可以转换为bool // 不过我找不到代替的方法。。。。。。。 if (n) { while (n--) ++i; } else { printf("You can not make a iterator -- while this iterator only have ++ in advance()"); } } // Distance类型被要求支持两个--操作和两个++操作,能转换为bool型 template <typename BidirectionalIterator, typename Distance> inline void _advance(BidirectionalIterator& i, Distance n, bidirectional_iterator_tag) { if (n) while (n--) ++i; else while (n++) --i; } template <typename RandomAccessIterator, typename Distance> inline void _advance(RandomAccessIterator& i, Distance n, random_access_iterator_tag) { // 原文是 i+=n;在这里有暗含i要支持+=这样的操作,是不合理的 i = i + n; } // 请记住使用&!!!! template <typename InputIterator, typename Distance> inline void advance(InputIterator& i, Distance n) { _advance(i, n, iterator_category(i)); } template <typename InputIterator, typename OutputIterator> inline OutputIterator _copy(InputIterator first, InputIterator last, OutputIterator res, input_iterator_tag) { // We'd better not use while (first != last) *res++ = *first++; // This method will be supposed to be written in the situation // we know what will the ++(int)operation do, and while it is much more // not effcient than ++() we should use ++() first; // so we use ++() here; for (; first != last; ++first, ++res) *res = *first; return res; } template <typename RandomAccessIterator, typename OutputIterator, typename Distance> inline OutputIterator _copy_distance(RandomAccessIterator first, RandomAccessIterator last, OutputIterator res, Distance*) { for (Distance d = last - first; d != 0; --d, ++res, ++first) *res = *first; return res; } template <typename RandomAccessIterator, typename OutputIterator> inline OutputIterator _copy(RandomAccessIterator first, RandomAccessIterator last, OutputIterator res, random_access_iterator_tag) { // 在这里我们已经知道了iterator的类型,所以不必传递random_access_iterator_tag _copy_distance(first, last, res, distance_type(first)); } template <typename InputIterator, typename OutputIterator> struct copy_dispatcher { OutputIterator operator()(InputIterator first, InputIterator last, OutputIterator result) { return _copy(first, last, result, iterator_category(first)); } }; template <typename T> inline T* _copy_ptr(const T* first, const T* last, T* result, __true_type) { const ptrdiff_t diff = last - first; memmove(result, first, sizeof(T) * diff); return result + diff; } template <typename T> inline T* _copy_ptr(const T* first, const T* last, T* result, __false_type) { _copy_distance(first, last, result, (ptrdiff_t*) (0)); } template <typename T> struct copy_dispatcher<T*, T*> { T* operator()(T* first, T* last, T* res) { return _copy_ptr(first, last, res, typename __type_traits<T>::has_trivial_assignment_operator()); } }; template <typename T> struct copy_dispatcher<const T*, T*> { T* operator()(const T* first, const T* last, T* res) { return _copy_ptr(first, last, res, typename __type_traits<T>::has_trivial_assignment_operator()); } }; template <typename InputIterator, typename OutputIterator> inline OutputIterator copy(InputIterator first, InputIterator last, OutputIterator res) { return copy_dispatcher<InputIterator, OutputIterator>()(first, last, res); } inline char* copy(const char* first, const char* last, char* result) { const ptrdiff_t diff = last - first; memmove(result, first, diff);// Cause sizeof(char) is 1 return result + diff; } inline wchar_t* copy(const wchar_t* first, const wchar_t* last, wchar_t* result) { const ptrdiff_t diff = last - first; memmove(result, first, sizeof(wchar_t) * diff); return result + diff; } // Easy , we copy the element to destination from the backward direction template <typename BidirectionalIterator_a, typename BidirectionalIterator_b> inline BidirectionalIterator_b _copy_backward(BidirectionalIterator_a first, BidirectionalIterator_a last, BidirectionalIterator_b res, input_iterator_tag) { // we will copy the element from the form one // of the res while (first != last) *--res = *--last; return res; } template <typename BidirectionalIterator_a, typename BidirectionalIterator_b, typename Distance> inline BidirectionalIterator_b _copy_backward_distance(BidirectionalIterator_a first, BidirectionalIterator_a last, BidirectionalIterator_b res, Distance*) { // Maybe !=() operation will come to much resources // so we'd better use a light type: distance Distance dis = last - first; while (dis != 0) { --dis; *--res = *--last; } return res; } template <typename BidirectionalIterator_a, typename BidirectionalIterator_b> inline BidirectionalIterator_b _copy_backward(BidirectionalIterator_a first, BidirectionalIterator_a last, BidirectionalIterator_b res, random_access_iterator_tag) { _copy_backward_distance(first, last, res, distance_type(first)); } template <typename BidirectionalIterator_a, typename BidirectionalIterator_b> struct copy_backward_dispatcher { BidirectionalIterator_b operator()(BidirectionalIterator_a first, BidirectionalIterator_a last, BidirectionalIterator_b res) { return _copy_backward_backward(first, last, res, iterator_category(first)); } }; template <typename T> inline T* _copy_backward_ptr(const T* first, const T* last, T* res, __true_type) { const ptrdiff_t diff = last - first; memmove(res - diff, first, sizeof(T) * diff); return res - diff; } template <typename T> inline T* _copy_backward_ptr(const T* first, const T* last, T* res, __false_type) { return _copy_backward_distance(first, last, res, (ptrdiff_t*) (0)); } template <typename T> struct copy_backward_dispatcher<T*, T*> { T* operator()(T* first, T* last, T* res) { return _copy_backward_ptr(first, last, res, typename __type_traits<T>::has_trivial_assignment_operator()); } }; template <typename T> struct copy_backward_dispatcher<const T*, T*> { T* operator()(const T* first, const T* last, T* res) { return _copy_backward_ptr(first, last, res, typename __type_traits<T>::has_trivial_assignment_operator()); } }; template <typename BidirectionalIterator_a, typename BidirectionalIterator_b> inline BidirectionalIterator_b copy_backward(BidirectionalIterator_a first, BidirectionalIterator_a last, BidirectionalIterator_b res) { return copy_backward_dispatcher<BidirectionalIterator_a, BidirectionalIterator_b>()(first, last, res); } inline char* copy_backward(const char* first, const char* last, char* result) { const ptrdiff_t diff = last - first; memmove(result - diff, first, diff);// Cause sizeof(char) is 1 return result - diff; } inline wchar_t* copy_backward(const wchar_t* first, const wchar_t* last, wchar_t* result) { const ptrdiff_t diff = last - first; memmove(result - diff, first, sizeof(wchar_t) * diff); return result - diff; } template <typename InputIterator, typename _Size, typename OutputIterator> inline OutputIterator _copy_n(InputIterator first, _Size size, OutputIterator res, input_iterator_tag) { while (size != 0) { --size; ++res; ++first; *res = *first;} return res; } template <typename RandomAccessIterator, typename _Size, typename OutputIterator> inline OutputIterator _copy_n(RandomAccessIterator first, _Size size, OutputIterator res, random_access_iterator_tag) { return copy(first, first + size, res); } // THis function is work for the situation that we // do not know last iterator, we just know the size template <typename InputIterator, typename _Size, typename OutputIterator> inline OutputIterator copy_n(InputIterator first, _Size size, OutputIterator res) { return _copy_n(first, size, res, iterator_category(first)); } template <typename InputIterator, typename Value> inline void fill(InputIterator first, InputIterator last, const Value& val) { while (first != last) { *first = val; ++first; } } template <typename InputIterator, typename _Size, typename Value> inline void fill_n(InputIterator first, _Size n, const Value& val) { while (n != 0) { *first = val; --n; ++first; } } _STL_NAMESPACE_END #endif