实际上在 Vector
与 SortedVector
这两个类中,没有太多内容,主要提供了一些给外部调用的接口而已。不过也有一些需要注意的内容,比如抽象类中的纯虚函数的实现,以及自定义的比较函数等等。
Vectoc
类继承自 VectorImpl
,它的大部分功能都是通过直接内部调用父类的函数来实现的。因此这个类的结构与实现都非常简单,以至于只需要一个头文件就能全部包含。
根据代码中的注释可以知道,这一主模板 Vector
类在使用 VectorImpl
时确保了类型安全性。这个类是开放给用户使用的。这个 Vector 和标准模板库中的那个用途应该是一样的,不过在实现上应该有所不同,具体差异其实不必深究,能用就行……
文件路径:system\core\libutils\include\utils\Vector.h
代码解释:
SortedVector
类,因为此处没有引用相应的头文件,但后面在构造函数中会用到它。iterator
是为了在一定程度上兼容 STL 中的 Vector
类。用过 STL 中的 Vector
的人应该比较熟悉这些操作了,主要就是基于 iterator
来对 Vector 中元素进行访问、控制、遍历等(注意使用 const_iterator
时不能对元素内容进行操作)。template <typename TYPE>
class SortedVector;
/*!
* The main templated vector class ensuring type safety
* while making use of VectorImpl.
* This is the class users want to use.
*/
template <class TYPE>
class Vector : private VectorImpl
{
public:
typedef TYPE value_type;
/*!
* Constructors and destructors
*/
Vector();
Vector(const Vector<TYPE>& rhs);
explicit Vector(const SortedVector<TYPE>& rhs);
virtual ~Vector();
/*! copy operator */
const Vector<TYPE>& operator = (const Vector<TYPE>& rhs) const;
Vector<TYPE>& operator = (const Vector<TYPE>& rhs);
const Vector<TYPE>& operator = (const SortedVector<TYPE>& rhs) const;
Vector<TYPE>& operator = (const SortedVector<TYPE>& rhs);
/*
* empty the vector
*/
inline void clear() { VectorImpl::clear(); }
/*!
* vector stats
*/
//! returns number of items in the vector
inline size_t size() const { return VectorImpl::size(); }
//! returns whether or not the vector is empty
inline bool isEmpty() const { return VectorImpl::isEmpty(); }
//! returns how many items can be stored without reallocating the backing store
inline size_t capacity() const { return VectorImpl::capacity(); }
//! sets the capacity. capacity can never be reduced less than size()
inline ssize_t setCapacity(size_t size) { return VectorImpl::setCapacity(size); }
/*!
* set the size of the vector. items are appended with the default
* constructor, or removed from the end as needed.
*/
inline ssize_t resize(size_t size) { return VectorImpl::resize(size); }
/*!
* C-style array access
*/
//! read-only C-style access
inline const TYPE* array() const;
//! read-write C-style access
TYPE* editArray();
/*!
* accessors
*/
//! read-only access to an item at a given index
inline const TYPE& operator [] (size_t index) const;
//! alternate name for operator []
inline const TYPE& itemAt(size_t index) const;
//! stack-usage of the vector. returns the top of the stack (last element)
const TYPE& top() const;
/*!
* modifying the array
*/
//! copy-on write support, grants write access to an item
TYPE& editItemAt(size_t index);
//! grants right access to the top of the stack (last element)
TYPE& editTop();
/*!
* append/insert another vector
*/
//! insert another vector at a given index
ssize_t insertVectorAt(const Vector<TYPE>& vector, size_t index);
//! append another vector at the end of this one
ssize_t appendVector(const Vector<TYPE>& vector);
//! insert an array at a given index
ssize_t insertArrayAt(const TYPE* array, size_t index, size_t length);
//! append an array at the end of this vector
ssize_t appendArray(const TYPE* array, size_t length);
/*!
* add/insert/replace items
*/
//! insert one or several items initialized with their default constructor
inline ssize_t insertAt(size_t index, size_t numItems = 1);
//! insert one or several items initialized from a prototype item
ssize_t insertAt(const TYPE& prototype_item, size_t index, size_t numItems = 1);
//! pop the top of the stack (removes the last element). No-op if the stack's empty
inline void pop();
//! pushes an item initialized with its default constructor
inline void push();
//! pushes an item on the top of the stack
void push(const TYPE& item);
//! same as push() but returns the index the item was added at (or an error)
inline ssize_t add();
//! same as push() but returns the index the item was added at (or an error)
ssize_t add(const TYPE& item);
//! replace an item with a new one initialized with its default constructor
inline ssize_t replaceAt(size_t index);
//! replace an item with a new one
ssize_t replaceAt(const TYPE& item, size_t index);
/*!
* remove items
*/
//! remove several items
inline ssize_t removeItemsAt(size_t index, size_t count = 1);
//! remove one item
inline ssize_t removeAt(size_t index) { return removeItemsAt(index); }
/*!
* sort (stable) the array
*/
typedef int (*compar_t)(const TYPE* lhs, const TYPE* rhs);
typedef int (*compar_r_t)(const TYPE* lhs, const TYPE* rhs, void* state);
inline status_t sort(compar_t cmp);
inline status_t sort(compar_r_t cmp, void* state);
// for debugging only
inline size_t getItemSize() const { return itemSize(); }
/*
* these inlines add some level of compatibility with STL. eventually
* we should probably turn things around.
*/
typedef TYPE* iterator;
typedef TYPE const* const_iterator;
inline iterator begin() { return editArray(); }
inline iterator end() { return editArray() + size(); }
inline const_iterator begin() const { return array(); }
inline const_iterator end() const { return array() + size(); }
inline void reserve(size_t n) { setCapacity(n); }
inline bool empty() const{ return isEmpty(); }
inline void push_back(const TYPE& item) { insertAt(item, size(), 1); }
inline void push_front(const TYPE& item) { insertAt(item, 0, 1); }
inline iterator erase(iterator pos) {
ssize_t index = removeItemsAt(static_cast<size_t>(pos-array()));
return begin() + index;
}
protected:
virtual void do_construct(void* storage, size_t num) const;
virtual void do_destroy(void* storage, size_t num) const;
virtual void do_copy(void* dest, const void* from, size_t num) const;
virtual void do_splat(void* dest, const void* item, size_t num) const;
virtual void do_move_forward(void* dest, const void* from, size_t num) const;
virtual void do_move_backward(void* dest, const void* from, size_t num) const;
};
文件路径:system\core\libutils\include\utils\Vector.h
Vector 类中大部分函数都是直接调用相应的父类函数进行实现的。但有几个例外,就是父类中的那几个纯虚函数,需要在此进行具体实现。我们可以先看看对应的代码。
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_construct(void* storage, size_t num) const {
construct_type( reinterpret_cast<TYPE*>(storage), num );
}
template<class TYPE>
void Vector<TYPE>::do_destroy(void* storage, size_t num) const {
destroy_type( reinterpret_cast<TYPE*>(storage), num );
}
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_copy(void* dest, const void* from, size_t num) const {
copy_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_splat(void* dest, const void* item, size_t num) const {
splat_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(item), num );
}
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_move_forward(void* dest, const void* from, size_t num) const {
move_forward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}
template<class TYPE>
UTILS_VECTOR_NO_CFI void Vector<TYPE>::do_move_backward(void* dest, const void* from, size_t num) const {
move_backward_type( reinterpret_cast<TYPE*>(dest), reinterpret_cast<const TYPE*>(from), num );
}
观察代码,可以注意到,这些函数都直接调用了某些函数(但非父类中实现的函数)来实现相应的功能。这些函数都是在 TypeHelpers.h
中具体实现的,这不在学习范围之内,不过可以看看其中一些具体实现是怎样的。
比如 do_splat
中用到的 splat_type
:
trivial
类型的 copy
操作,从 where
位置开始,依次构造 n
个元素空间(并且是调用拷贝构造函数,拷贝对象是 what 指向的元素)。trivial
类型的 copy
操作,则直接从 where
位置开始,依次赋值为 what
指向的元素,共赋值 n
次。template<typename TYPE> inline
void splat_type(TYPE* where, const TYPE* what, size_t n) {
if (!traits<TYPE>::has_trivial_copy) {
while (n > 0) {
n--;
new(where) TYPE(*what);
where++;
}
} else {
while (n > 0) {
n--;
*where++ = *what;
}
}
}
TypeHelpers.h
中都是类似的,非常底层的实现,这个头文件中将这些操作都封装了起来,简化了其它类的实现代码,同时也使得这些代码更易于阅读。
与 Vector
不同,SortedVector
继承自 SortedVectorImpl
。
虽然它们有一个共同的先代(VectorImpl
),但很明显,SortedVector
是一个总能保持元素按照指定顺序排列的向量,而 Vector
则需要调用其内置的 sort
函数才能使得元素有序。
文件路径:system\core\libutils\include\utils\SortedVector.h
这部分与 Vector
类基本一致,先是一些基本操作(此处多了 merge
函数),然后是为了与 STL 减容而给出的关于 iterator
的相关操作,最后就是父类中的纯虚函数(注意这里多了一个 do_compare
)。
template <class TYPE>
class SortedVector : private SortedVectorImpl
{
friend class Vector<TYPE>;
public:
typedef TYPE value_type;
/*!
* Constructors and destructors
*/
SortedVector();
SortedVector(const SortedVector<TYPE>& rhs);
virtual ~SortedVector();
/*! copy operator */
const SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs) const;
SortedVector<TYPE>& operator = (const SortedVector<TYPE>& rhs);
/*
* empty the vector
*/
inline void clear() { VectorImpl::clear(); }
/*!
* vector stats
*/
//! returns number of items in the vector
inline size_t size() const { return VectorImpl::size(); }
//! returns whether or not the vector is empty
inline bool isEmpty() const { return VectorImpl::isEmpty(); }
//! returns how many items can be stored without reallocating the backing store
inline size_t capacity() const { return VectorImpl::capacity(); }
//! sets the capacity. capacity can never be reduced less than size()
inline ssize_t setCapacity(size_t size) { return VectorImpl::setCapacity(size); }
/*!
* C-style array access
*/
//! read-only C-style access
inline const TYPE* array() const;
//! read-write C-style access. BE VERY CAREFUL when modifying the array
//! you must keep it sorted! You usually don't use this function.
TYPE* editArray();
//! finds the index of an item
ssize_t indexOf(const TYPE& item) const;
//! finds where this item should be inserted
size_t orderOf(const TYPE& item) const;
/*!
* accessors
*/
//! read-only access to an item at a given index
inline const TYPE& operator [] (size_t index) const;
//! alternate name for operator []
inline const TYPE& itemAt(size_t index) const;
//! stack-usage of the vector. returns the top of the stack (last element)
const TYPE& top() const;
/*!
* modifying the array
*/
//! add an item in the right place (and replace the one that is there)
ssize_t add(const TYPE& item);
//! editItemAt() MUST NOT change the order of this item
TYPE& editItemAt(size_t index) {
return *( static_cast<TYPE *>(VectorImpl::editItemLocation(index)) );
}
//! merges a vector into this one
ssize_t merge(const Vector<TYPE>& vector);
ssize_t merge(const SortedVector<TYPE>& vector);
//! removes an item
ssize_t remove(const TYPE&);
//! remove several items
inline ssize_t removeItemsAt(size_t index, size_t count = 1);
//! remove one item
inline ssize_t removeAt(size_t index) { return removeItemsAt(index); }
/*
* these inlines add some level of compatibility with STL.
*/
typedef TYPE* iterator;
typedef TYPE const* const_iterator;
inline iterator begin() { return editArray(); }
inline iterator end() { return editArray() + size(); }
inline const_iterator begin() const { return array(); }
inline const_iterator end() const { return array() + size(); }
inline void reserve(size_t n) { setCapacity(n); }
inline bool empty() const{ return isEmpty(); }
inline iterator erase(iterator pos) {
ssize_t index = removeItemsAt(pos-array());
return begin() + index;
}
protected:
virtual void do_construct(void* storage, size_t num) const;
virtual void do_destroy(void* storage, size_t num) const;
virtual void do_copy(void* dest, const void* from, size_t num) const;
virtual void do_splat(void* dest, const void* item, size_t num) const;
virtual void do_move_forward(void* dest, const void* from, size_t num) const;
virtual void do_move_backward(void* dest, const void* from, size_t num) const;
virtual int do_compare(const void* lhs, const void* rhs) const;
};
文件路径:system\core\libutils\include\utils\SortedVector.h
实现方面,和 Vector
也是类似的,主要调用父类实现的函数,还有 TypeHelpers.h
中封装的一些底层操作。
需要注意的是 do_compare
的实现,它调用了 TypeHelpers.h
中的 compare_type
函数。
从这里可以看到,用于比较的是 lhs
与 rhs
指针所指向的元素的值,如果 TYPE
是 int
,则此处就是直接比较数值大小了。
template<class TYPE>
int SortedVector<TYPE>::do_compare(const void* lhs, const void* rhs) const {
return compare_type( *reinterpret_cast<const TYPE*>(lhs), *reinterpret_cast<const TYPE*>(rhs) );
}
compare_type
又是基于 strictly_order_type
函数实现的,此处看起来有点绕,但是可以分别假定 lhs
与 rhs
的值,看看其观察其返回值。
最终可以发现:
lhs > rhs
时,函数返回值为 1
;lhs = rhs
时,返回值为 0
;lhs < rhs
时,返回值为 -1
。template<typename TYPE> inline
int strictly_order_type(const TYPE& lhs, const TYPE& rhs) {
return (lhs < rhs) ? 1 : 0;
}
template<typename TYPE> inline
int compare_type(const TYPE& lhs, const TYPE& rhs) {
return strictly_order_type(rhs, lhs) - strictly_order_type(lhs, rhs);
}
这两个类中涉及到了 TypeHelpers.h
中封装的一些函数,这些函数都是非常底层的实现,有时间可以仔细看看。
比较需要关注的可能是 SortedVector
中定义的比较函数,它比较的是指针指向的元素的值,这个值取决于 TYPE
这个类型的 operator *
的具体定义。