#ifndef __POINTER_AMV
	#define __POINTER_AMV

//#include <iostream.h>

/*
Plantilla de clase que simula el comportamiento de un apuntador a 'type' y permite incorporar
estos apuntadores a los contenedores que no tienen una especialización para apuntadores.

El tipo para construir esta clase debe soportar la funcion clone(), que devuelve un apuntador
a un objeto igual al que apunta el apuntador original. Esta funcion permite que se copien objetos
derivados de un objeto base, cuyo apuntador es el tipo con el que se contruye el contenedor.

*** Siempre obtiene una réplica del objeto con el que se contruye o que se asigna ***
Si se le asigna un apuntador, no saca réplica, si se le asigna un pointer sí.
Si se construye con un apuntador, no saca réplica, si se construye con un pointer, si.

No toma el mismo apuntador que se le asigna en:
ipointer<piece> p=new piece();
p.ptype es un nuevo apuntador a piece(), de tal manera que un objeto queda perdido, pues no
hay modo de recuperar su dirección.

*/

namespace amv	{

//puntero a objetos que no son de tipos iguales, pero comparten la misma base en una relacion de herencia

template <class type>
class ipointer	{
type *ptype;
public:
	ipointer(): ptype(0)
		{
		}
	ipointer(const ipointer &p)
		{
		if(p.ptype)
			ptype=p->clone();
		else
			ptype=0;
		}
	ipointer(type *p)
		{
		ptype=p;
		}
	ipointer(const type &t)
		{
		ptype=new type(t);
		}

	~ipointer()
		{
		delete ptype;
		}
	//función para desatar el apuntador, sólo debe hacerse esto si en alguna otra parte
	//liberaremos la memoria correspondiente a este apuntador, o si el apuntador se ha asignado
	//a otro objeto ipointer, que al destruirse hará la liberación de memoria
	void untie()
		{
		ptype=0;
		}
	ipointer &operator=(const ipointer &p)
		{
		delete ptype;
		if(p.ptype)
			ptype=p->clone();
		else
			ptype=0;

		return *this;
		}
	ipointer &operator=(type *p)
		{
		delete ptype;
		ptype=p;

		return *this;
		}
	ipointer &operator=(const type &t)
		{
		delete ptype;
		ptype=new type(t);

		return *this;
		}

	type &operator*()
		{
		return *ptype;
		}
	const type &operator*() const
		{
		return *ptype;
		}
	type *operator->()
		{
		return ptype;
		}
	const type *operator->() const
		{
		return ptype;
		}
	operator bool() const
		{
		return ptype;
		}
	operator type *() const
		{
		return ptype;
		}
	operator type *()
		{
		return ptype;
		}

/*
	bool operator==(const pointer &p) const
		{
		return *ptype==*p;
		}

	bool operator!=(const pointer &p) const
		{
		return !(*ptype==*p);
		}

	bool operator<(const pointer &p) const
		{
		return *ptype<*p;
		}
*/



	

};

//puntero a objetos de tipo completamente iguales

template <class type>
class pointer	{
type *ptype;
public:
	pointer(): ptype(0)
		{
		}
	pointer(const pointer &p)
		{
		if(p.ptype)
			ptype=new type(*p);
		else
			ptype=0;
		}
	pointer(type *p)
		{
		ptype=p;
		}
	pointer(const type &t)
		{
		ptype=new type(t);
		}

	~pointer()
		{
		delete ptype;
		}
	void untie()
		{
		ptype=0;
		}

	pointer &operator=(const pointer &p)
		{
		delete ptype;
		if(p.ptype)
			ptype=new type(*p);
		else
			ptype=0;

		return *this;
		}
	pointer &operator=(type *p)
		{
		delete ptype;
		ptype=p;

		return *this;
		}
	pointer &operator=(const type &t)
		{
		delete ptype;
		ptype=new type(t);

		return *this;
		}

	type &operator*()
		{
		return *ptype;
		}
	const type &operator*() const
		{
		return *ptype;
		}
	type *operator->()
		{
		return ptype;
		}
	const type *operator->() const
		{
		return ptype;
		}
	operator bool() const
		{
		return ptype;
		}
	operator type *() const
		{
		return ptype;
		}
	operator type *()
		{
		return ptype;
		}



/*
	bool operator==(const pointer &p) const
		{
		return *ptype==*p;
		}

	bool operator!=(const pointer &p) const
		{
		return !(*ptype==*p);
		}

	bool operator<(const pointer &p) const
		{
		return *ptype<*p;
		}
*/



	

};

}

#endif