2

We started using templates this week in our CSS class, they seem fairly straight forward however, when we started diving into it in our lab, some problems we can't figure out started showing up.

We are getting the following errors:

../Lab7PartC/DLNode.cpp:13:5: error: invalid use of template-name ‘lab7::DLNode’ without an argument list
../Lab7PartC/DLNode.cpp:20:5: error: invalid use of template-name ‘lab7::DLNode’ without an argument list
../Lab7PartC/DLNode.cpp:26:5: error: expected unqualified-id before ‘template’
../Lab7PartC/DLNode.cpp:33:5: error: invalid use of template-name ‘lab7::DLNode’ without an argument list

Here is the relevant class .cpp file:

/*
 * DLNode.cpp
 *
 *  Created on: Mar 29, 2013
 *      Author: tony
 */

#include <cstddef>
#include "DLNode.h"

namespace lab7 {

    DLNode::DLNode() {
        data = 0;
        next = NULL;
        prev = NULL;
    }

    template<class T>
    DLNode::DLNode(T d) {
        data = d;
        next = NULL;
        prev = NULL;
    }

    template<class T>
    DLNode::DLNode(T d, DLNode* n, DLNode* p) {
        data = d;
        next = n;
        prev = p;
    }

    DLNode::~DLNode() {
        delete next;
    }



} /* namespace lab7 */

Here is the relevant .h file:

/*
 * DLNode.h
 *
 *  Created on: Mar 29, 2013
 *      Author: tony
 */

#ifndef DLNODE_H_
#define DLNODE_H_

namespace lab7 {
    template<class T>
    class DLNode {
    public:
        DLNode();
        DLNode(T data_in);
        DLNode(T data_in, DLNode* n, DLNode* p);
        virtual ~DLNode();

        void setNext(DLNode* n) {
            next = n;
        }

        void setPrev(DLNode* p) {
            prev = p;
        }

        int getData() {
            return data;
        }

        DLNode* getNext() {
            return next;
        }

        DLNode* getPrev() {
            return prev;
        }
    private:
        T data;
        DLNode* next;
        DLNode* prev;
    };

} /* namespace lab7 */
#endif /* DLNODE_H_ */

We've spent the evening trying to figure it out, and appreciate any advice on the topic. Thanks.

I hate to bother you again, but I modified the header files to include the entire definition as you suggested, and this is what I have, this time I am including the additional class that uses the node class:

/*
 * DLNode.h
 *
 *  Created on: Mar 29, 2013
 *      Author: tony
 */

#ifndef DLNODE_H_
#define DLNODE_H_

namespace lab7 {

    template<class T>
    class DLNode {
    public:
        DLNode<T>();
        DLNode<T>(T data_in);
        DLNode<T>(T data_in, DLNode* n, DLNode* p);
        ~DLNode<T>();

        void setNext<T>(DLNode* n) {
            next = n;
        }

        void setPrev<T>(DLNode* p) {
            prev = p;
        }

        int getData<T>() {
            return data;
        }

        DLNode* getNext<T>() {
            return next;
        }

        DLNode* getPrev<T>() {
            return prev;
        }
    private:
        T data;
        DLNode* next;
        DLNode* prev;
    };

    template<class T>
    DLNode<T>::DLNode() {
        data = 0;
        next = NULL;
        prev = NULL;
    }

    template<class T>
    DLNode<T>::DLNode(T d) {
        data = d;
        next = NULL;
        prev = NULL;
    }

    template<class T>
    DLNode<T>::DLNode(T d, DLNode* n, DLNode* p) {
        data = d;
        next = n;
        prev = p;
    }

    template<class T>
    DLNode<T>::~DLNode() {
        delete next;
    }
} /* namespace lab7 */
#endif /* DLNODE_H_ */

--and the additional list class header file:

/*
 * DLList.h
 *
 *  Created on: Mar 29, 2013
 *      Author: tony
 */

#ifndef DLLIST_H_
#define DLLIST_H_


namespace lab7 {

    class DLNode<T>;

    template<class T>
    class DLList {
    public:
        DLList();
        virtual ~DLList();
        void insert(T data);
        void print();
        bool search(const T key);
        bool searchandremove(const T key);
        void swap();
        DLNode* findNode(const T key);
    private:
        DLNode* first;
    };

    template<class T>
    DLList<T>::DLList() {
        first = NULL;
    }

    template<class T>
    DLList<T>::~DLList() {
        delete first;
    }

    template<class T>
    void DLList<T>::insert(T data) {
        DLNode<T>* temp = first;
        first = new DLNode(data, first, NULL);
        if (temp == NULL)
            return;
        temp->setPrev(first);
    }

    template<class T>
    void DLList<T>::print() {
        DLNode* temp = first;
        while (temp != NULL) {
            cout << temp->getData() << " ";
            temp = temp->getNext();
        }
        cout << endl;
    }

    template<class T>
    bool DLList<T>::search(const T key) {
        DLNode* temp = new DLNode;
        bool found = false;
        for (temp = first; temp != NULL; temp = temp->getNext()) {
            if (temp->getData() == key)
                found = true;
        }
        return found;
    }

    template<class T>
    bool DLList<T>::searchandremove(const T key) {
        DLNode* prev = new DLNode;
        DLNode* next = new DLNode;
        DLNode* toDelete = new DLNode;
        toDelete = findNode(key);
        if (toDelete != NULL) {
            prev = toDelete->getPrev();
            next = toDelete->getNext();
            toDelete->setNext(NULL);
            toDelete->setPrev(NULL);
            if (toDelete == first) {
                first = next;
                next->setPrev(first);
            } else {

                prev->setNext(next);
                if (next != NULL)
                    next->setPrev(prev);
            }
            delete toDelete;
            return true;
        }
        return false;
    }

    template<class T>
    DLNode* DLList<T>::findNode(const T key) {
        DLNode* temp = new DLNode;
        for (temp = first; temp != NULL; temp = temp->getNext()) {
            if (temp->getData() == key)
                return temp;
        }
        return NULL;
    }

    template<class T>
    void DLList<T>::swap() {
        DLNode* last = new DLNode;
        //navigate to second to last node
        for (last = first; last->getNext() != NULL; last = last->getNext()) {
        }
        last->getPrev()->setNext(first);
        first->setPrev(last->getPrev());
        last->setPrev(NULL);
        last->setNext(first->getNext());
        first->getNext()->setPrev(last);
        first->setNext(NULL);
        first = last;

    }
} /* namespace lab7 */
#endif /* DLLIST_H_ */

This came with an additional plethora of errors I don't understand:

In file included from ../Lab7PartC/Lab7B.cpp:13:0:
../Lab7PartC/DLList.h:14:11: error: ‘DLNode’ is not a template
../Lab7PartC/DLList.h:14:18: error: ‘T’ was not declared in this scope
../Lab7PartC/DLList.h: In member function ‘void lab7::DLList<T>::insert(T)’:
../Lab7PartC/DLList.h:43:9: error: ‘lab7::DLNode’ is not a template
../Lab7PartC/DLList.h:47:13: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h: In member function ‘void lab7::DLList<T>::print()’:
../Lab7PartC/DLList.h:54:25: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:55:24: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h: In member function ‘bool lab7::DLList<T>::search(T)’:
../Lab7PartC/DLList.h:62:28: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:64:53: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:65:21: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h: In member function ‘bool lab7::DLList<T>::searchandremove(T)’:
../Lab7PartC/DLList.h:73:28: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:74:28: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:75:32: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:78:28: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:79:28: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:80:21: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:81:21: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:84:21: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:87:21: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:89:25: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h: In member function ‘lab7::DLNode* lab7::DLList<T>::findNode(T)’:
../Lab7PartC/DLList.h:99:28: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:100:53: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:101:21: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h: In member function ‘void lab7::DLList<T>::swap()’:
../Lab7PartC/DLList.h:109:28: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:111:32: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:111:64: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:113:13: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:114:14: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:114:28: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:115:13: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:116:13: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:116:28: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:117:14: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:118:14: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h: In member function ‘void lab7::DLList<T>::insert(T) [with T = int]’:
../Lab7PartC/Lab7B.cpp:23:26:   instantiated from here
../Lab7PartC/DLList.h:44:9: error: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: error: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h: In member function ‘bool lab7::DLList<T>::searchandremove(T) [with T = int]’:
../Lab7PartC/Lab7B.cpp:34:32:   instantiated from here
../Lab7PartC/DLList.h:91:13: warning: possible problem detected in invocation of delete operator:
../Lab7PartC/DLList.h:75:17: warning: ‘toDelete’ has incomplete type
../Lab7PartC/DLList.h:14:11: warning: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:91:13: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined.
../Lab7PartC/DLList.h: In destructor ‘lab7::DLList<T>::~DLList() [with T = int]’:
../Lab7PartC/Lab7B.cpp:46:1:   instantiated from here
../Lab7PartC/DLList.h:38:9: warning: possible problem detected in invocation of delete operator:
../Lab7PartC/DLList.h:38:9: warning: invalid use of incomplete type ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:14:11: warning: forward declaration of ‘struct lab7::DLNode’
../Lab7PartC/DLList.h:38:9: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined.
twoLeftFeet
  • 693
  • 1
  • 5
  • 25
  • 1
    Don't put templates implementations in CPP files... – Pubby Apr 06 '13 at 04:50
  • A little background on these files, we received them as they are except for any of the template implementation. Our job was then to add the template functionality to allow the class to handle any numerical data type. I'm not sure what you mean @Pubby, in order to handle multiple types of data input, doesn't there need to be a template implementation in the .cpp? – twoLeftFeet Apr 06 '13 at 04:56
  • For starters, your DLNode *class* is a template, not just a couple members. That .cpp file should not even exist. All of this should be in the header. See [this question](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) concerning how you implement template functionality. To answer your question about template implementation in the CPP, there *doesn't need to be a cpp* is the answer. – WhozCraig Apr 06 '13 at 04:57
  • Oh, I see what you are saying. That does make sense, so the header file can contain the function bodies, in the case that you implement a template? Correct me if I'm wrong, but I understood that the header file was where you declare the functions, and the .cpp was where you put the function bodies. – twoLeftFeet Apr 06 '13 at 05:04
  • @roemhildtga Correct, but you have to think of templates as a stencil in which you add a missing piece and the compiler generates the code *for you*. The compiler therefore, must see that stencil anywhere it might be used, and hidden in a source file makes it local only to that transition unit (compilable entity), thereby hiding the code definition the compiler needs. See Pubby's answer; it drives this concept nicely, as well as the linked article. – WhozCraig Apr 06 '13 at 05:07

3 Answers3

1

First off, templates should only be implemented in header files. See Why can templates only be implemented in the header file?

Now, DLNode is not a class, it's a class template, and so it should always have a template argument, ie DLNode<T> or DLNode<int>. Now, you might be wondering why you didn't do this in the class body, such as void setNext(DLNode* n), and that's because the argument is implicit in the class scope.

What I wrote seems confusing, but this is how everything should look:

template<class T>
DLNode<T>::DLNode() {
    data = 0;
    next = NULL;
    prev = NULL;
}

template<class T>
DLNode<T>::DLNode(T d) {
    data = d;
    next = NULL;
    prev = NULL;
}

template<class T>
DLNode<T>::DLNode(T d, DLNode* n, DLNode* p) {
    data = d;
    next = n;
    prev = p;
}

template<class T>
DLNode<T>::~DLNode() {
    delete next;
}

As I said, this code needs to be in the header file instead of the cpp file. Although once you do this, it becomes rather pointless to define them outside of the class body, and so just define everything inside the class body:

namespace lab7 {
    template<class T>
    class DLNode {
    public:
        DLNode() {
            data = 0;
            next = NULL;
            prev = NULL;
        }

        // ...
    };

} /* namespace lab7 */
Community
  • 1
  • 1
Pubby
  • 51,882
  • 13
  • 139
  • 180
  • I made the changes you suggested (at least I think I did), and it seems I may have made a mistake somewhere, please see the edits to the question. – twoLeftFeet Apr 06 '13 at 05:48
  • @roemhildtga `class DLNode;` is not a correct declaration as it's missing `template`, and you need to add the argument in certain places, like `DLNode` inside `DLList`. – Pubby Apr 06 '13 at 07:29
  • It still amazes me how many errors can be caused by just a few misplaced lines. Thanks for the help! – twoLeftFeet Apr 06 '13 at 14:44
0
//forgot something here?
DLNode::~DLNode() {
    delete next;
}

Same about the constructor. Use the template declaration before every function definition.

atoMerz
  • 7,534
  • 16
  • 61
  • 101
0

At least there are two problems: your default constructor and destructor declarations do not start with template<class T>.

Ellioh
  • 5,162
  • 2
  • 20
  • 33