// matriz.h
#if !defined( _MATRIZ_H_ )
#define _MATRIZ_H_
#include "dimensiones.h"
#include "elemento_accedido.h"

//////////////////////////////////////////////////////////////////
// Plantilla de clase para construir matrices multidimensionales

template <class T> class CMatriz
{
    friend class CElementoAccedido<T>;

    T *m_pMatriz;   // matriz lineal de elementos de tipo T
    CDimensiones m_Dimensiones; // dimensiones de la matriz
  public:
    // Constructor: matriz de una dimensión
    CMatriz(int s1) : m_Dimensiones(1, s1, 0, 0, 0, 0, 0)
    {
      m_pMatriz = new T[m_Dimensiones.TotalElementos()];
    }

    // Constructor: matriz de dos dimensiones
    CMatriz(int s1, int s2) : m_Dimensiones(2, s1, s2, 0, 0, 0, 0)
    {
      m_pMatriz = new T[m_Dimensiones.TotalElementos()];
    }

    // Constructor: matriz de tres dimensiones
    CMatriz(int s1, int s2, int s3) : 
    m_Dimensiones(3, s1, s2, s3, 0, 0, 0)
    {
      m_pMatriz = new T[m_Dimensiones.TotalElementos()];
    }

    // Constructor: matriz de cuatro dimensiones
    CMatriz(int s1, int s2, int s3, int s4) : 
    m_Dimensiones(4, s1, s2, s3, s4, 0, 0)
    {
      m_pMatriz = new T[m_Dimensiones.TotalElementos()];
    }

    // Constructor: matriz de cinco dimensiones
    CMatriz(int s1, int s2, int s3, int s4, int s5) : 
    m_Dimensiones(5, s1, s2, s3, s4, s5, 0)
    {
      m_pMatriz = new T[m_Dimensiones.TotalElementos()];
    }

    // Constructor: matriz de seis dimensiones
    CMatriz(int s1, int s2, int s3, int s4, int s5, int s6) : 
    m_Dimensiones(6, s1, s2, s3, s4, s5, s6)
    {
      m_pMatriz = new T[m_Dimensiones.TotalElementos()];
    }
    // Constructor copia
    CMatriz(const CMatriz<T> &x);
    
    // Devuelve un objeto que contiene una referencia al objeto
    // CMatriz y los subíndices del elemento accedido
    CElementoAccedido<T> operator[](int subind)
    {
      return CElementoAccedido<T>(*this, subind);
    }
    // Asignación
    CMatriz<T> &operator=(const CMatriz<T> &x);
};

// Constructor copia
template <class T> inline CMatriz<T>::CMatriz(const CMatriz<T> &x) :
m_Dimensiones(x.m_Dimensiones)
{
   size_t tam = x.m_Dimensiones.TotalElementos();
   m_pMatriz = new T[tam];
   memcpy(m_pMatriz, x.m_pMatriz, tam*sizeof(T));
}

// Asignación
template <class T>
inline CMatriz<T> &CMatriz<T>::operator=(const CMatriz<T> &x)
{
   m_Dimensiones = x.m_Dimensiones;
   delete [] m_pMatriz;
   size_t tam = x.m_Dimensiones.TotalElementos();
   m_pMatriz = new T[tam];
   memcpy(m_pMatriz, x.m_pMatriz, tam*sizeof(T));
   return *this;
}
//////////////////////////////////////////////////////////////////

#endif // _MATRIZ_H_

