Выставляю на суд общественности вектор для хранения указателей. Сразу скажу, что этот код предназначен для уменьшения объёма полученного кода (причём скорости работы он не добавляет
).
Если в программе используется большое количество векторов на различные указатели, то происходит дублирование кода и, следовательно, раздувается в размерах exe-шник. Например так:
std::vector<Type1*> vect1;
std::vector<Type2*> vect2;
std::vector<Type3*> vect3;
std::vector<Type4*> vect4;
std::vector<Type5*> vect5;
Код работы со всеми векторами почти идентичен. Но компилятор из-за разницы типов гененирует для каждого вектора свой код. Оговорюсь, что такая ситуация происходит при отключенной генерации inline-функций.
Идея шаблона такая. В себе он хранит std::vector<void*>. А затем, по мере надобности он приводит void* к нужному типу данных. Код вектора для указателей не совсем повторяет код стандартного вектора. Кроме того, добавлено несколько дополнительных функций:
void remove_nulls() — удаление нулевых указателей
void clear_items() — удаление хранящихся в векторе указателей и очистка списка.
Для сортировки и поиска объектов в векторе прилагается несколько шаблонов сравнения:
ptr_less — объект меньше
ptr_equal — объект равен
ptr_not_equal — объект не равен
Вот пример использования шаблона:
ptr_vector<float> pt;
// добавляем элементы
pt.push_back(new float(10));
pt.push_back(new float(15));
pt.push_back(new float(5));
// сортируем
std::sort(pt.begin(), pt.end(), ptr_less<float*>());
// удаляем первый элемент
delete pt[0];
pt.erase(pt.begin());
// удаляем элементы
pt.clear_items();
Ещё раз повторюсь, что этот код нужно использовать при отключенной генерации inline-функций.
#ifndef PTR_VECTOR_H
#define PTR_VECTOR_H
#include <vector>
#include <algorithm>
/*------------------------*/
/* class ptr_vector */
/*------------------------*/
template <typename T> class ptr_vector
{
private:
typedef void* internal_type;
typedef void** internal_iterator;
typedef std::vector<internal_type> items_type;
typedef items_type::size_type size_type;
items_type items;
public:
typedef T* value_type;
typedef T** iterator;
// конструкторы/деструктор
ptr_vector() {}
ptr_vector(size_type size) { items.resize(size, NULL); }
virtual ~ptr_vector() {}
// доступ к элементам
value_type& operator [] (size_type index) { return (value_type)items[index]; }
const value_type& operator [] (size_type index) const { return (value_type)items[index]; }
value_type& at(size_type index) { return (value_type)items.at(index); }
const value_type& at(size_type index) const { return (value_type)items.at(index); }
value_type& back() { return (value_type)items.back(); }
value_type& front() { return (value_type)items.front(); }
// начало-конец
iterator begin() { return (iterator)items.begin(); }
iterator end() { return (iterator)items.end(); }
// размер
size_type size() const { return items.size(); }
size_type capacity() const { return items.capacity(); }
void resize(size_type new_size) { items.resize(new_size, NULL); }
void reserve(size_type res_size) { items.reserve(res_size); }
void clear() { items.clear(); }
bool empty() const { return items.empty(); }
/* управление элементами: */
// копирование
void assign(size_type count, const value_type val) { items.assign(count, (internal_type)val); }
void assign(iterator from, iterator to) { items.assign((internal_iterator)from, (internal_iterator)to); }
// удаление
void erase(size_type pos) { items.erase(items.begin()+pos); };
void erase(iterator pos) { items.erase((internal_iterator)pos); }
void erase(iterator from, iterator to) { items.erase((internal_iterator)from, (internal_iterator)to); }
// вставка
void insert(size_type pos, const value_type value) { items.insert(items.begin()+pos, value); }
void insert(iterator pos, const value_type value) { items.insert((internal_iterator)pos, value); }
void insert(iterator pos, size_type count, const value_type value) { items.insert((internal_iterator)pos, count, value); }
// push/pop
void push_back(const value_type value) { items.push_back(value); }
void pop_back() { items.pop_back(); }
void push_front(const value_type value) { items.insert(items.begin(), value); }
void pop_front() { items.erase( items.begin() ); }
// удаляет нулевые указатели
void remove_nulls()
{
std::vector<internal_type>::iterator it = std::remove(items.begin(), items.end(), (internal_type)NULL);
items.erase( it, items.end() );
}
// удалят указатели и очищает список
void clear_items()
{
for (size_type i = 0; i < items.size(); i++) delete (value_type)items[i];
items.clear();
}
};
/*----------------------------------------------------*/
/* Шаблонные предикатные функции для указателей */
/*----------------------------------------------------*/
// bool ptr_less( )
//--------------------------
template <class T> struct ptr_less
{
bool operator() (const T e1, const T e2) { return (*e1 < *e2); }
};
// bool ptr_equal( )
//---------------------------
template <class T> struct ptr_equal
{
bool operator() (const T e1, const T e2) { return (*e1 == *e2); }
};
// bool ptr_not_equal( )
//---------------------------
template <class T> struct ptr_not_equal
{
bool operator() (const T e1, const T e2) { return (*e1 != *e2); }
};
#endif
... << RSDN@Home 1.0 beta 6a >>