//------------------------------------------------------------ #include <string> #include <vector> #include <stdarg.h> #include <algorithm> template<class T, int Dim> class Array { // объявляем дружественным для вызова простого конструктора friend class std::vector< Array<T, Dim> >; // пользователю вряд ли нужно создавать массив без размера, // поэтому в private Array() { m_Data=0; } public: Array(int Sizes[Dim]) { Resize(Sizes); m_Data=0; } Array(int Size0, ...) { va_list Marker; va_start(Marker, Size0); int Sizes[Dim]; Sizes[0]=Size0; for (int Index=1; Index<Dim; Index++) { Sizes[Index]=va_arg(Marker, int); } va_end(Marker); Resize(Sizes); m_Data=0; } Array(const Array<T, Dim> &Ref) { m_Vector=Ref.m_Vector; m_Data=(Ref.m_Data) ? new T(*Ref.m_Data) : 0; } ~Array() { delete m_Data; } // динамическое масштабирование массива void Resize(int Sizes[Dim]) { if (Dim!=0) { m_Vector.resize(Sizes[0]); for (int Index=0; Index<Sizes[0]; Index++) { m_Vector[Index].Resize(Sizes+1); } } } Array<T, Dim> operator= (const Array<T, Dim> &Ref) { // перед присвоением сжимаем массив до нулевых размеров if (Dim!=0) { // ставим Dim+1, чтобы компилятор не выдавал ошибку при Dim==0 int Sizes[Dim+1]; std::memset(Sizes, 0, Dim*sizeof(int)); // будут вызваны деструкторы для всех элементов Resize(Sizes); } return Array<T, Dim>(Ref); } Array<T, Dim> &operator= (const T &Value) { if (Dim==0) { delete m_Data; // удаляем старое значение m_Data=new T(Value); // создаем новое } return *this; } Array<T, Dim-1> &operator[] (int Index) { // как и положено в С++, корректность индекса не проверяем return m_Vector[Index]; } operator T&() { // неявное преобразование типа, работает только для Dim==0, // иначе ошибка return *m_Data; } private: std::vector< Array<T, ((Dim-1)>0 ? (Dim-1) : 0) > > m_Vector; T *m_Data; }; // примеры использования int main() { Array<int, 2> data(7, 7); // двумерный массив int 7х7 int Sizes[2]={5, 5}; data.Resize(Sizes); // превращаем его в 5х5 data[1][2]=-1; // индексирование работает как для lvalue int x=data[1][2]; // так и для rvalue data[3][3]=11; x=data[3][3];
// пятимерный массив double 7х7х7х7х7 Array<double, 5> double_arr(7, 7, 7, 7, 7); double_arr[0][0][2][3][1]=11;
// копируем двумерный массив data в data2 Array<int, 2> data2(data); Array<int, 2> data3(2, 1); data3[0][0]=15; data3=data; // присваиваем data3 массив data
// четырехмерный строковый массив из 1 элемента Array<std::string, 4> str(1, 1, 1, 1); str[0][0][0][0]="xe"; // присваиваем значение
// некорректно, вызывает ошибку выполнения, так как массив двумерный // x=data[2]; // некорректно, вызывает ошибку выполнения // Array<char *, 4> Quad(data);
return 0; } //------------------------------------------------------------
|