ptr_vector - очередной велосипед
От: ArtDenis Россия  
Дата: 04.05.03 07:47
Оценка: 14 (1)
Выставляю на суд общественности вектор для хранения указателей. Сразу скажу, что этот код предназначен для уменьшения объёма полученного кода (причём скорости работы он не добавляет ).

Если в программе используется большое количество векторов на различные указатели, то происходит дублирование кода и, следовательно, раздувается в размерах 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 >>
[ 🎯 Дартс-лига Уфы | 🌙 Программа для сложения астрофото ]
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.