I'm trying to create a link list template in Visual Studio and I'm getting "class template has already been declared as a non-class template" error. I have the header file with the declarations and a LinkList.tem file with the definitions. I #include LinkList.tem
at the end of the header file to get it to compile. I have an example where it is done this way and it works fine. I have replicated that example as best as I can see with my link list files, but still I get the error.
LinkList.h
#ifndef LINKLIST_H
#define LINKLIST_H
#include <iostream>
#include <fstream>
#include <ostream>
#include <string>
#include "Node.h"
template <typename T>
class LinkList { // This line is where I get the error
public:
LinkList() { first = last = nullptr; } // empty container
// value Semantic Functions
// copy constructor
LinkList(const LinkList<T>& source);
// assignment operator
LinkList<T>& operator=(const LinkList<T>& source);
// destructor
~LinkList() { free(); }
// add / append / insert
void append(T dataIn);
void prepend(T dataIn);
// remove / Erase
void removeFirst();
bool remove(T item);
// clearAll
void clearAll() { free(); }
// isEmpty
//Find or contains
bool isEmpty() { return first == nullptr; }
// readFile
bool readFile(std::string fileName);
// writeFile
bool writeFile(std::string fileName);
void print();
int getSize();
Node<T>* at(int count);
Node<T>* getRandomItem();
private:
Node<T>* first;
Node<T>* last;
// alloc
Node<T>* alloc(T dataIn);
// free
void free();
Node<T>* find(T item);
};
#include "LinkList.tem"
#endif
and LinkList.tem
template<typename T>
LinkList<T>::LinkList(const LinkList<T>& source) {
first = last = nullptr;
for (Node<T>* ptr = source.first; ptr != nullptr; ptr = ptr->next)
this->append(ptr->data);
}
template<typename T>
LinkList<T>& LinkList<T>::operator=(const LinkList<T>& source) {
if (this == &source)
return *this;
free();
first = last = nullptr;
for (Node<T>* ptr = source.first; ptr != nullptr; ptr = ptr->next)
this->append(ptr->data);
}
template<typename T>
void LinkList<T>::append(T dataIn) {
Node<T>* ptr = alloc(dataIn);
if (isEmpty())
first = last = ptr;
else {
last->next = ptr;
last = ptr;
}
}
template<typename T>
void LinkList<T>::prepend(T dataIn) {
Node<T>* ptr = alloc(dataIn);
if (isEmpty())
first = last = ptr;
else {
ptr->next = first;
first = ptr;
}
}
template <typename T>
bool LinkList<T>::remove(T item) {
if (isEmpty())
return false;
else if (item == first->data)
removeFirst();
else {
Node<T>* previous;
Node<T>* temp;
for (previous = first; previous != nullptr; previous->next) {
if (previous->next->data == item)
break;
}
temp = previous->next;
previous->next = temp->next;
delete temp;
}
return false;
}
template<typename T>
void LinkList<T>::removeFirst() {
Node<T>* tmp = first;
if (isEmpty())
return;
else if (!isEmpty() && first == last) {
delete tmp;
first = last = nullptr;
}
else {
first = tmp->next;
delete tmp;
}
}
template<typename T>
bool LinkList<T>::readFile(std::string fileName) {
std::ifstream inFS;
T data;
inFS.open(fileName);
if (!inFS.is_open()) {
std::cout << "Could not open " << fileName << std::endl;
return false;
}
while (!inFS.eof()) {
inFS >> data;
append(data);
}
inFS.close();
return true;
}
template<typename T>
bool LinkList<T>::writeFile(std::string fileName) {
std::ofstream outFS;
outFS.open(fileName);
if (!outFS.is_open()) {
std::cout << "Error opening " << fileName << std::endl;
return false;
}
for (Node<T>* ptr = first; ptr != nullptr; ptr = ptr->next)
outFS << ptr->data << std::endl;
outFS.close()
return true;
}
template<typename T>
void LinkList<T>::print() {
for (Node<T>* cursor = first; cursor != nullptr; cursor = cursor->next)
std::cout << cursor->data << std::endl;
}
template<typename T>
int LinkList<T>::getSize() {
int counter = 0;
if (first == nullptr)
return counter;
for (Node<T>* temp = first; temp != nullptr; temp = temp->next)
counter ;
return counter;
}
template<typename T>
Node<T>* LinkList<T>::at(int count) {
Node<T>* temp = first;
if (count > getSize())
return nullptr;
for (int i = 1; i < count; i )
temp = temp->next;
return temp
}
template<typename T>
Node<T>* LinkList<T>::getRandomItem() {
srand(time(NULL));
return at(rand() % getSize() 1)
}
template<typename T>
Node<T>* LinkList<T>::alloc(T dataIn) {
return new Node<T>(dataIn);
}
template<typename T>
void LinkList<T>::free() {
while (!isEmpty()) {
removeFirst();
}
}
template <typename T>
Node<T>* LinkList<T>::find(T item) {
if (isEmpty())
return nullptr;
for (Node<T>* tmp = first; tmp != nullptr; tmp = tmp->next)
if (tmp->data == item)
return tmp;
return nullptr;
}
For completeness Node.h
#ifndef NODE_H
#define NODE_H
template <typename T>
class Node {
friend class LinkList;
public:
// Constructors
Node() : data(T()), next(nullptr) {}
Node(T dataIn) : data(dataIn), next(nullptr) {}
private:
// data members
T data;
Node<T>* next;
};
#endif
CodePudding user response:
You're friend declaration in Node
has to say that LinkList
is a template:
template <typename T>
class Node {
template <typename X> friend class LinkList;
CodePudding user response:
Your problem is that you need to forward declare LinkList class template into Node.h header file:
template <typename T>
class LinkList;
And some ";" typos
Your final code will be:
LinkList.h
#ifndef LINKLIST_H
#define LINKLIST_H
#include <iostream>
#include <fstream>
#include <ostream>
#include <string>
#include "Node.h"
template <typename T>
class LinkList { // This line is where I get the error
public:
LinkList() { first = last = nullptr; } // empty container
// value Semantic Functions
// copy constructor
LinkList(const LinkList<T>& source);
// assignment operator
LinkList<T>& operator=(const LinkList<T>& source);
// destructor
~LinkList() { free(); }
// add / append / insert
void append(T dataIn);
void prepend(T dataIn);
// remove / Erase
void removeFirst();
bool remove(T item);
// clearAll
void clearAll() { free(); }
// isEmpty
//Find or contains
bool isEmpty() { return first == nullptr; }
// readFile
bool readFile(std::string fileName);
// writeFile
bool writeFile(std::string fileName);
void print();
int getSize();
Node<T>* at(int count);
Node<T>* getRandomItem();
private:
Node<T>* first;
Node<T>* last;
// alloc
Node<T>* alloc(T dataIn);
// free
void free();
Node<T>* find(T item);
};
#include "LinkList.tem"
#endif
LinkList.tem
template<typename T>
LinkList<T>::LinkList(const LinkList<T>& source) {
first = last = nullptr;
for (Node<T>* ptr = source.first; ptr != nullptr; ptr = ptr->next)
this->append(ptr->data);
}
template<typename T>
LinkList<T>& LinkList<T>::operator=(const LinkList<T>& source) {
if (this == &source)
return *this;
free();
first = last = nullptr;
for (Node<T>* ptr = source.first; ptr != nullptr; ptr = ptr->next)
this->append(ptr->data);
}
template<typename T>
void LinkList<T>::append(T dataIn) {
Node<T>* ptr = alloc(dataIn);
if (isEmpty())
first = last = ptr;
else {
last->next = ptr;
last = ptr;
}
}
template<typename T>
void LinkList<T>::prepend(T dataIn) {
Node<T>* ptr = alloc(dataIn);
if (isEmpty())
first = last = ptr;
else {
ptr->next = first;
first = ptr;
}
}
template <typename T>
bool LinkList<T>::remove(T item) {
if (isEmpty())
return false;
else if (item == first->data)
removeFirst();
else {
Node<T>* previous;
Node<T>* temp;
for (previous = first; previous != nullptr; previous->next) {
if (previous->next->data == item)
break;
}
temp = previous->next;
previous->next = temp->next;
delete temp;
}
return false;
}
template<typename T>
void LinkList<T>::removeFirst() {
Node<T>* tmp = first;
if (isEmpty())
return;
else if (!isEmpty() && first == last) {
delete tmp;
first = last = nullptr;
}
else {
first = tmp->next;
delete tmp;
}
}
template<typename T>
bool LinkList<T>::readFile(std::string fileName) {
std::ifstream inFS;
T data;
inFS.open(fileName);
if (!inFS.is_open()) {
std::cout << "Could not open " << fileName << std::endl;
return false;
}
while (!inFS.eof()) {
inFS >> data;
append(data);
}
inFS.close();
return true;
}
template<typename T>
bool LinkList<T>::writeFile(std::string fileName) {
std::ofstream outFS;
outFS.open(fileName);
if (!outFS.is_open()) {
std::cout << "Error opening " << fileName << std::endl;
return false;
}
for (Node<T>* ptr = first; ptr != nullptr; ptr = ptr->next)
outFS << ptr->data << std::endl;
outFS.close();
return true;
}
template<typename T>
void LinkList<T>::print() {
for (Node<T>* cursor = first; cursor != nullptr; cursor = cursor->next)
std::cout << cursor->data << std::endl;
}
template<typename T>
int LinkList<T>::getSize() {
int counter = 0;
if (first == nullptr)
return counter;
for (Node<T>* temp = first; temp != nullptr; temp = temp->next)
counter ;
return counter;
}
template<typename T>
Node<T>* LinkList<T>::at(int count) {
Node<T>* temp = first;
if (count > getSize())
return nullptr;
for (int i = 1; i < count; i )
temp = temp->next;
return temp;
}
template<typename T>
Node<T>* LinkList<T>::getRandomItem() {
srand(time(NULL));
return at(rand() % getSize() 1);
}
template<typename T>
Node<T>* LinkList<T>::alloc(T dataIn) {
return new Node<T>(dataIn);
}
template<typename T>
void LinkList<T>::free() {
while (!isEmpty()) {
removeFirst();
}
}
template <typename T>
Node<T>* LinkList<T>::find(T item) {
if (isEmpty())
return nullptr;
for (Node<T>* tmp = first; tmp != nullptr; tmp = tmp->next)
if (tmp->data == item)
return tmp;
return nullptr;
}
Node.h
#ifndef NODE_H
#define NODE_H
template <typename T>
class LinkList;
template <typename T>
class Node {
friend class LinkList<T>;
public:
// Constructors
Node() : data(T()), next(nullptr) {}
Node(T dataIn) : data(dataIn), next(nullptr) {}
private:
// data members
T data;
Node<T>* next;
};
#endif