Обычные массивы как контейнеры STL. Интерфейсный класс для массива

   
На этом шаге мы рассмотрим реализацию интерфейсного класса для массива.

   
В своей книге "The C++ Programming Language", 3rd Edition, Бьярн Страуструп описывает очень полезный интерфейсный класс для обычных массивов.
Он гораздо надежнее обычных массивов, хотя и не уступает им по быстродействию. Наконец, он является хорошим примером контейнера STL, определяемого
пользователем. В данном случае используется вариант с интерфейсным классом, то есть стандартный контейнерный интерфейс реализуется как оболочка вокруг массива.
Определение класса саггау (сокращенное от "С array" или "constant size array") выглядит так:

#include <cstddef>

template<class T,std::size_t thesize>
class carray {
  private:
    T v[thesize];  // Массив фиксированного размера
                   // для элементов типа Т
  public:
    // Определения типов
    typedef T        value_type;
    typedef T*       iterator;
    typedef const T* const_iterator;
    typedef T&       reference;
    typedef const T& const_reference;
    typedef std::size_t     size_type;
    typedef std::ptrdiff_t  difference_type;

    // Поддержка итераторов
    iterator begin() { return v; }
    const_iterator begin() const { return v; }
    iterator end() { return v+thesize; }
    const_iterator end() const { return v+thesize; }

    // Прямой доступ к элементам
    reference operator[] (std::size_t i) { return v[i]; }
    const_reference operator[](std::size_t i) const { return v[i]; }

    // Фиксированный размер
    size_type size() const { return thesize; }
    size_type max_size() const { return thesize; }

    // Преобразование к обычному массиву
    T* as_array() { return v; }
};

   
Пример использования класса carray:

//---------------------------------------------------------------------------

#include <vcl.h>
#include <algorithm>
#include <functional>
#include <string>
#include <iostream>

#include "carray.hpp"
#include <conio.h> //необходимо для getch()

#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused
using namespace std;


std::string ToRus(const std::string &in)
{
  char *buff = new char [in.length()+1];
  CharToOem(in.c_str(),buff);
  std::string out(buff);
  delete [] buff;
  return out;
}

template <class T>
inline void PRINT_ELEMENTS (const T& coll, const char* optcstr="")
{
  typename T::const_iterator pos;
  std::cout << ToRus(optcstr);
  for (pos=coll.begin(); pos!=coll.end(); ++pos) {
    std::cout <<*pos <<' ';
  }
  std::cout << std::endl;
}


int main(int argc, char* argv[])
{
  carray<int,10> a;

  for (unsigned i=0; i<a.size(); ++i) {
    a[i] = i+1;
  }
  cout << ToRus("Исходный массив:\n");
  PRINT_ELEMENTS(a);

  reverse (a.begin(),a.end());
  cout << ToRus("Массив в обратном порядке:\n");
  PRINT_ELEMENTS(a);

  transform(a.begin(),a.end(),  // Источник
            a.begin(),          // Приемник
            negate<int>());     // Операция
  cout << ToRus("Массив противоположных чисел:\n");
  PRINT_ELEMENTS(a);

  getch();
  return 0;
}

//---------------------------------------------------------------------------

Текст этого примера можно взять здесь.

   
Как видно из приведенного кода, прямое взаимодействие с контейнером осуществляется через операции общего контейнерного интерфейса (функции
begin(), end() и оператор []). Следовательно, в вашем распоряжении также оказываются различные операции, вызывающие функции
begin() и end(), - такие, как алгоритмы и вспомогательная функция PRINT_ELEMENTS().

   
Результат выполнения программы выглядит так:


Рис.1. Результат работы приложения

   
На следующем шаге мы рассмотрим хэш-таблицы.



Вы можете оставить комментарий, или Трекбэк с вашего сайта.

Оставить комментарий