He intentado implementar mi propia clase de lista vinculada para fines didácticos.Error del compilador al declarar una clase de amigo de plantilla dentro de una clase de plantilla
Especifiqué la clase "Lista" como amigo dentro de la declaración del iterador, pero parece que no compila.
Estas son las interfaces de las 3 clases que he usado:
Node.h:
#define null (Node<T> *) 0
template <class T>
class Node {
public:
T content;
Node<T>* next;
Node<T>* prev;
Node (const T& _content) :
content(_content),
next(null),
prev(null)
{}
};
Iterator.h:
#include "Node.h"
template <class T>
class Iterator {
private:
Node<T>* current;
Iterator (Node<T> *);
public:
bool isDone() const;
bool hasNext() const;
bool hasPrevious() const;
void stepForward();
void stepBackwards();
T& currentElement() const;
friend class List<T>;
};
Lista. h
#include <stdexcept>
#include "Iterator.h"
template <class T>
class List {
private:
Node<T>* head;
Node<T>* tail;
unsigned int items;
public:
List();
List (const List<T>&);
List& operator = (const List<T>&);
~List();
bool isEmpty() const {
return items == 0;
}
unsigned int length() const {
return items;
}
void clear();
void add (const T&);
T remove (const T&) throw (std::length_error&, std::invalid_argument&);
Iterator<T> createStartIterator() const throw (std::length_error&);
Iterator<T> createEndIterator() const throw (std::length_error&);
};
Y este es el programa de prueba que he estado tratando de correr:
trial.cpp
using namespace std;
#include <iostream>
#include "List/List.cc"
int main()
{
List<int> myList;
for (int i = 1; i <= 10; i++) {
myList.add(i);
}
for (Iterator<int> it = myList.createStartIterator(); !it.isDone(); it.stepForward()) {
cout << it.currentElement() << endl;
}
return 0;
}
Cuando intento compilar, el compilador me da los siguientes errores :
Iterator.h: 26: error: 'Lista' no es una plantilla
Iterator.h: En instanciación de 'iterador':
trial.cpp: 18: instancia de aquí
Iterator.h: 12: error: argumento de plantilla requerida para la 'Lista struct '
List.cc: En función miembro 'Iterator Lista :: createStartIterator() const [con T = int]':
trial.cpp: 18: instancia de aquí
Iterator.h: 14: error: 'Iterator :: iterador (Nodo *) [con T = int]' es privada
Lista .cc: 120: error: en este contexto
Parece que no está reconociendo la declaración del amigo. ¿Dónde me equivoqué?
No defina su propia macro nula (o NULL, o nada relacionado). En el caso de inicializar miembros de datos, '0' funciona bien. –
Sé que es feo, solo fue temporal. Pero estaba bastante seguro de que C++ no permitía la conversión implícita. –
Los lanzamientos nunca son implícitos, pero las conversiones sí lo son. (Dos caras de la misma moneda, podría decir, y "conversión" también se usa para nombrar métodos que convierten un valor entre otros usos, pero ese es un tipo diferente de conversión.) Lo que necesita para inicializar un puntero es otro puntero de tipo adecuado, o una constante de puntero nulo; '0' es una constante de puntero nulo perfectamente fina (' NULL' también, si lo prefiere). –