Del código que has puesto yo veo los siguientes problemas:
Te falta un punto y coma después de
t_arista:
Código C++:
Ver originaltypedef arista<datoarista_t,datonodo_t> t_arista
struct TratarAristaConNiveles
Te falta cerrar una llave:
Código C++:
Ver originalstruct ImprimirArbol:public TratarAristaConNiveles
{
ImprimirArbol(std::pair<pArista,int>par, std::list<pArista>&l):TratarAristaConNiveles(par,l){}
void operator()(std::pair<pArista,int>P)
{
std::cout<<P.second<<"-";
std::cout<<"|";
for (int i=0;i<P.second;i++)
{
std::cout<<"----";
}
std::cout<<">";
} // <<<---- ESTA!!!!
..................//aquí ya tengo otro tipo de error, pero no es el que me preocupa ahora
};
Y con eso a mí ya me compila.
Ahora una pequeña labor de refactorización:
El código de
functores.h no necesita conocer la clase
grafo sino únicamente a
arista y
nodo. Parece lógico entonces mover estas dos clases a un fichero independiente para que
functores.h no tenga que incluir
grafo.h. También puedes eliminar las
declaration forward de
arista y
nodo que tienes en
functores.h.
arista.h
Código C++:
Ver original#ifndef ARISTA_H
#define ARISTA_H
template <typename,typename>
struct nodo;
template <typename DATOA, typename DATON>
struct arista
{
DATOA datoarista;
nodo<DATON,DATOA>* destino;
arista<DATOA,DATON>* siguiente;
arista<DATOA,DATON>* anterior;
// ...
};
#endif // ARISTA_H
nodo.h
Código C++:
Ver original#ifndef NODO_H
#define NODO_H
template<typename, typename>
struct arista;
template <typename DATON, typename DATOA>
struct nodo
{
DATON datonodo;
unsigned short int nPadres;
nodo<DATON,DATOA>* siguiente;
arista<DATOA,DATON>* adyacente;
// ...
};
#endif // NODO_H
Por otro lado no veo nada en functores.h que impida convertir las clases en templates para no tener que crear especializaciones en ese punto:
Código C++:
Ver original#ifndef FUNCTORES_H
#define FUNCTORES_H
#include <iomanip>
#include "arista.h"
#include "nodo.h"
template<class DATOA, class DATON>
struct TratarAristaConNiveles
{
typedef nodo<DATON,DATOA>* pNodo;
typedef arista<DATOA,DATON>* pArista;
//typedef arista<MedCert,Concepto>* pArista;
std::pair<pArista,int>pareja;
std::list<pArista> &listaAristasConMediciones;
TratarAristaConNiveles(std::pair<pArista,int>par, std::list<pArista>&l):pareja(par),listaAristasConMediciones(l){}
virtual void operator()(std::pair<pArista,int>P)=0;
};
template<class DATOA, class DATON>
struct ImprimirArbol
: public TratarAristaConNiveles<DATOA,DATON>
{
// ...
};
El código anterior no compilará porque un template no puede definir una función virtual pura. Hay dos posibles formas de solucionarlo: más herencia o darle una implementación básica a dicha función. Yo personalmente prefiero la primera, pero no es implementable porque la firma del operador función es dependiente de los tipos del template así que solo nos queda la segunda opción:
Código C++:
Ver originaltemplate<class DATOA, class DATON>
struct TratarAristaConNiveles
{
typedef nodo<DATON,DATOA>* pNodo;
typedef arista<DATOA,DATON>* pArista;
//typedef arista<MedCert,Concepto>* pArista;
std::pair<pArista,int>pareja;
std::list<pArista> &listaAristasConMediciones;
TratarAristaConNiveles(std::pair<pArista,int>par, std::list<pArista>&l):pareja(par),listaAristasConMediciones(l){}
virtual void operator()(std::pair<pArista,int>P)
{}
};
Ahora el problema que tenemos es que la clase hija no va a reconocer las declaraciones de
pNodo y
pArista declaradas en
TratarAristaConNiveles. Este error tiene que ver con la forma en la que se tratan los templates en C++.
La forma más sencilla de lidiar con este problema, desde mi punto de vista, pasa por declarar una función
traits que declare por sí misma los tipos
pArista y
pNodo para no tener que redeclararlos cada dos por tres:
Código C++:
Ver originaltemplate<class,class>
struct arista;
template<class,class>
struct nodo;
template<class DATOA, class DATON>
struct traits
{
typedef arista<DATOA,DATON>* pArista;
typedef nodo<DATON,DATOA>* pNodo;
};
Y se usa así:
Código C++:
Ver originaltemplate<class DATOA, class DATON>
struct TratarAristaConNiveles
{
typedef traits<DATOA,DATON> myTraits;
typedef typename myTraits::pNodo pNodo;
typedef typename myTraits::pArista pArista;
//typedef arista<MedCert,Concepto>* pArista;
std::pair<pArista,int>pareja;
std::list<pArista> &listaAristasConMediciones;
TratarAristaConNiveles(std::pair<pArista,int>par,
std::list<pArista>&l)
: pareja(par),
listaAristasConMediciones(l)
{ }
virtual void operator()(std::pair<pArista,int>P)=0;
};
template<class DATOA, class DATON>
struct ImprimirArbol
: TratarAristaConNiveles<DATOA,DATON>
{
typedef typename TratarAristaConNiveles<DATOA,DATON>::myTraits myTraits;
typedef typename myTraits::pNodo pNodo;
typedef typename myTraits::pArista pArista;
ImprimirArbol(std::pair<pArista,int>par,
std::list<pArista>&l)
: TratarAristaConNiveles<DATOA,DATON>(par,l)
{ }
};
o así (si te quieres ahorrar un alias):
Código C++:
Ver originaltemplate <typename DATOA, typename DATON>
struct arista
{
typedef typename traits<DATOA,DATON>::pArista pArista;
typedef typename traits<DATOA,DATON>::pNodo pNodo;
DATOA datoarista;
pNodo destino;
pArista siguiente;
pArista anterior;
};
typename hay que ponerlo porque el tipo del que intentamos crear el alias es dependiente de un template... cosas del lenguaje.
Con C++11 quedaría algo más elegante, desde mi punto de vista:
Código C++:
Ver originalstruct TratarAristaConNiveles
{
using myTraits = traits<DATOA,DATON>;
using pNodo = typename myTraits::pNodo;
using pArista = typename myTraits::pArista;
};
template<class DATOA, class DATON>
struct ImprimirArbol
: TratarAristaConNiveles<DATOA,DATON>
{
using myTraits = typename TratarAristaConNiveles<DATOA,DATON>::myTraits;
using pNodo = typename myTraits::pNodo;
using pArista = typename myTraits::pArista;
};
La ventaja de usar la clase
traits es que podemos arrastrar esas definiciones a donde nos plazca de forma algo más sencilla que hacerlo a mano, donde tienes que recordar el orden de
DATOA y
DATON en cada declaración de
nodo y
arista.
Para rematar, dado que ahora tenemos templates nuevos, hay que actualizar el archivo
grafo.h. Ahí podemos eliminar las
declaration forward de
TratarAristaConNiveles e
ImprimirArbol, además de actualizar la firma de algunas funciones:
Código C++:
Ver originalvoid recorrerGrafoConNiveles(pNodo& inicio,
TratarAristaConNiveles<DATOA,DATON>& tratamiento,
int n=0);
Y creo que como primer paso es suficiente. Seguir refactorizando ese código lleva su tiempo sobretodo para comprenderlo (paso imprescindible para que el nuevo código funcione correctamente jejeje), pero con estos cambios al menos es compilable.
Yo empezaría por meter la clase
traits en
grafo para tener una declaración unificada de los tipos
pArista y
pNodo.
Un saludo.