// elemento_accedido.h
#if !defined( _ELEMENTO_ACCEDIDO_H_ )
#define _ELEMENTO_ACCEDIDO_H_
#include "subindices.h"

//////////////////////////////////////////////////////////////////
// Indica la matriz a la que accedemos y los subíndices del
// elemento accedido

template <class T> class CMatriz;

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

    CMatriz<T> &m_Matriz;     // referencia a la matriz accedida
    CSubindices m_Subindices; // subíndices del elemento accedido

    // El constructor
    CElementoAccedido(CMatriz<T> &a, int PrimerSubind):m_Matriz(a), 
    m_Subindices(a.m_Dimensiones.nDimensiones(), PrimerSubind)
    {
    }

    T &ObtenerElemento(); // busca el elemento en el espacio físico

  public:
    CElementoAccedido<T> &operator[](int subind)
    {
      m_Subindices.AnyadirSigSubind(subind);
      return *this;
    }

    // Convierte el resultado final de una operación de subíndices
    // en una referencia al elemento referenciado, o asigna
    // el elemento referenciado.
    operator T &() const
    {
      return ((CElementoAccedido<T> *)this)->ObtenerElemento();
    }

    // Asigna o devuelve el valor a/de un elemento de la matriz
    T &operator=(const T &arg) { return ObtenerElemento() = arg; }
};

// Buscar el elemento en el espacio físico (matriz lineal)
template <class T> T &CElementoAccedido<T>::ObtenerElemento()
{
  static T nada;
  // El nº de dimensiones tiene que ser igual al nº de subíndices
  if (m_Matriz.m_Dimensiones.nDimensiones() != 
      m_Subindices.nSubindsActual())
  {
    cerr << "Número de dimensiones y subíndices diferentes\n";
    return nada;
  }

  // Calcular el desplazamiento en el espacio físico de la matriz
  // correspondiente a los subíndices del elemento elegido. También
  // se verifica la validez de los subíndices.
  int desplazamiento = 
        m_Subindices.Desplazamiento(m_Matriz.m_Dimensiones);
  if (desplazamiento != -1)
    return m_Matriz.m_pMatriz[desplazamiento];
  else
    return nada;
}
//////////////////////////////////////////////////////////////////

#endif // _ELEMENTO_ACCEDIDO_H_

