Home > Blockchain >  "class template has already been declared as a non-class template" error for my linklist t
"class template has already been declared as a non-class template" error for my linklist t

Time:11-18

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
  • Related