1

I just started using template.

I want to create a linked list class which stores the address of Type (could be an object). Here is the layout of my project:

linkedlist.h
node.h
node.cpp
linkedlist.cpp
main.cpp

Node.h

template <class Type> struct Node
{
public:
    Node<Type>();
    Node<Type>(Type* x = 0, Node* pNext = 0);
    Type* data;
    Node* next;
};

Node.cpp

#include "node.h"

template<class Type> Node<Type>::Node()
{
    next = 0;
    data = 0;
}
template<class Type> Node<Type>::Node(Type* item, Node* ptrNext)
{
    next = ptrNext;
    data = item;
}

linkedlist.h

#include "node.h"

template <class Type> class LinkedList
{
private:
    Node<Type>* root;

public:
    LinkedList<Type>();
    ~LinkedList<Type>();
    void insert(Type*);
    void remove(Type*);
};

linkedlist.cpp

#include "linkedlist.h"

template <class Type> LinkedList<Type>::LinkedList()
{
    root = 0;
}

template <class Type> LinkedList<Type>::~LinkedList()
{
    Node* p;
    while(p = root)
    {
        root = p->next;
        delete p;
    }
}
// many more....

In main.cpp, I have the following:

int main()
{
    int *ptrA, *ptrB;
    int a = 100, b = 10;

    ptrA = &a;
    ptrB = &b;

    LinkedList<int>myList;
    myList.insert(ptrA);
    return 0;
}

and compiler threw linker errors:

1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall LinkedList<int>::~LinkedList<int>(void)" (??1?$LinkedList@H@@QAE@XZ) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "public: void __thiscall LinkedList<int>::insert(int *)" (?insert@?$LinkedList@H@@QAEXPAH@Z) referenced in function _main
1>main.obj : error LNK2019: unresolved external symbol "public: __thiscall LinkedList<int>::LinkedList<int>(void)" (??0?$LinkedList@H@@QAE@XZ) referenced in function _main

Attempted Solution:

I called LinkedListmyList() instead. This can resolve the linker error, but I will not be able to call any member function.

myList.insert(ptrA) will say "Error: Expression must have a class type" if I put ().

So clearly this is not working.

What's the problem? I think the whole implementation has problems....

Thanks for your time.

CppLearner
  • 16,273
  • 32
  • 108
  • 163
  • 1
    possible duplicate of [Why can templates only be implemented in the header file?](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – Flexo Dec 20 '11 at 02:08
  • or http://stackoverflow.com/questions/3705740/c-lnk2019-error-unresolved-external-symbol-template-classs-constructor-and or http://stackoverflow.com/questions/3680312/linker-error-lnk2019 – Flexo Dec 20 '11 at 02:09
  • Seems like an homework. What compiler? – Jaffa Dec 20 '11 at 02:10
  • Is the syntax `Node();` inside the class definition allowed? I've always just seen `Node()`. Apparently [it doesn't compile on IdeOne](http://ideone.com/yeH2U) – Seth Carnegie Dec 20 '11 at 02:11
  • @awoodland C++ standard does NOT specifies that template HAVE TO be implemented in header files. (But the related feature is only implemented by very few compiler which claims to be 100% standard compliant. Therefore you're right to point it out, even if it's not a rule). – Jaffa Dec 20 '11 at 02:11
  • 3
    Templates don't work that way... also, you should learn about constructor-initializer lists. – Kerrek SB Dec 20 '11 at 02:12
  • @Geffroy It isn't homework. I am just writing it on my own. – CppLearner Dec 20 '11 at 02:13
  • I realize I am doing this totally wrong. I will get back at this later. I am going to read all links suggested. Thanks. – CppLearner Dec 20 '11 at 02:14
  • 1
    @Geoffroy The standard talks in terms of translation units, but given that C++11 removed the export keyword that's pretty much the practical way to go about it... – Flexo Dec 20 '11 at 02:14
  • @awoodland Yes it's true, but once again C++11 is not yet entirely supported :) – Jaffa Dec 20 '11 at 02:20
  • @Geoffroy : Yes, but as you mentioned, only one company ever implemented `export template` in the first place, so whether it's deprecated or not doesn't change the fact that next-to-no-one offers it as an option in the first place. – ildjarn Dec 20 '11 at 03:49

1 Answers1

4

Move the stuff from linkedlist.cpp .. to linkedlist.h

As it's declaring a 'template for making code' the machine code doesn't actually exist until you give the compiler the type you want to use.

For example, as long as all the template code is visible to the compiler, as soon as you go: LinkedList<int>myList the compiler creates the solid real class that makes a linkedlist of ints. In your case, the compiler can't see the template code, so isn't able to generate the machine code.


in c++11 you can say 'extern template': http://en.wikipedia.org/wiki/C%2B%2B11#Extern_template

in the header file, then implement the 'int' version in your linkeList.cpp file .. and it'll be available in main.cpp when it tries to use it.

This gives the advantage of the compiler not having to generate the machine code in every .cpp file where the template is used and makes compiling faster.

It can be done in c++98 too .. but it's a bit more tricky and not 100% portable as I understand it .. easier to just generate the code everywhere. Here's a good blurb on it for gnu gcc: http://gcc.gnu.org/onlinedocs/gcc/Template-Instantiation.html

matiu
  • 7,469
  • 4
  • 44
  • 48