linker problems

hey,im having linker error issues with this program im writing
example:
[Linker error] undefined reference to `llist<int>::llist()'

header:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#ifndef LList_h_
#define LList_h_
#include <iostream>
template<class itemtype> 
class llist
{
template<itemtype> 
friend std::ostream& operator<<(std::ostream & , llist<itemtype> &);
      private:     
      struct nodetype
      {
      itemtype item;
      nodetype *next;
      };
      nodetype *first, *last;      
      public:
             llist();
             void firstinsert(itemtype);
             void frontinsert(itemtype);
             void endinsert(itemtype);
             void inorderinsert(itemtype);
             bool search(itemtype);
             bool remove (itemtype); 
             bool listempty();
             itemtype firstitem();
             itemtype lastitem();
             ~llist();
};
#endif 


implementation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#include "LList.h"
#include<iostream>
template <class itemtype>
llist<itemtype>::llist()
{  
             
   first=last=0;
}
template <class itemtype>
void llist<itemtype>::firstinsert(itemtype x)
{
     first= new nodetype;
     last= first;
     first->item =x;
     first->next = 0;
}
template <class itemtype>
void llist<itemtype>::frontinsert(itemtype x)
{
     nodetype *newnode;
     newnode= new nodetype;
     newnode->item =x;
     newnode->next=first;
     first=newnode;
}
template <class itemtype>
void llist<itemtype>::endinsert(itemtype x)
{
     nodetype *newnode;
     newnode= new nodetype;
     newnode->item =x;
     newnode->next=0;
     last->next=newnode;
     last=newnode;
}
template <class itemtype>
void llist<itemtype>::inorderinsert(itemtype x)
{
     nodetype *cur;
     nodetype *prev;
     
     nodetype *newnode;
     newnode= new nodetype;
     newnode->item =x;
     newnode->next=0;
     if(x<=first->item)
     {
       newnode->next=first;
       first=newnode;
     }
     else if (x>=last->item)
     {
      last->next=newnode;
     last=newnode;
     }
     else
     {
         prev=first;
         cur=first->next;
         while(x>cur->item)
         {
          prev=cur;
          cur=cur->next;
          }
     }
}
template <class itemtype>
bool llist<itemtype>::listempty()
{
return(first==0);
}
template <class itemtype>
itemtype llist<itemtype>::firstitem()
{
return first->item;
}
template <class itemtype>
itemtype llist<itemtype>::lastitem()
{
return last->item;
}
template <class itemtype>
bool llist<itemtype>::search(itemtype x)
{
     nodetype *cur;
     cur=first;
     while ((cur!=0)&&(x!=cur->item))
     {
           cur=cur->next;
     }
     return(cur!=0);
}
template <class itemtype>
llist<itemtype>::~llist()
{
     nodetype *delnode;
     while(first!=0)
     {
       delnode=first;
       first=first->next;
       delete delnode;
     }
}
template <class itemtype>
bool llist<itemtype>::remove (itemtype x)
{
     nodetype *cur, *prev;
     nodetype *delnode;
     prev=0;
     cur=first;
      while ((cur!=0)&&(x!=cur->item))
     { 
            prev=cur;
            cur=cur->next;
            if(cur==0)
              return 0;
            else
                delnode=cur;
                if(prev==0)
                {   
                    first=first->next;
                }
                else
                {
                prev->next=cur->next;
                if (cur==last)
                   last=prev;
                }
                delete delnode;
                return 1;
     }
}

template <class itemtype> 
std::ostream& operator<<(std::ostream &output,llist<itemtype> &l)
{  
        typename llist<itemtype>::nodetype *cur;
        cur=l.first;
        while(cur!=0)
        {
           output<<cur->item<<"|";
           cur=cur->next;
           }
        return output;
}


main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "LList.h"
#include<iostream>
int main()
{
    llist<int> i;
    llist<char> c;
    
    i.firstinsert(1);
    i.frontinsert(2);
    i.endinsert(4);
    i.inorderinsert(3);
    
    c.firstinsert('c');
    c.frontinsert('a');
    c.endinsert('r');
    c.inorderinsert('t');
    
    
    std::cout<<c<<std::endl;
    std::cout<<i<<std::endl;
    
    system("pause");
    return 0;
}
    


any help is appreciated
Move all your implementation stuff from LList.cpp and put it into LList.h


It is the easiest way (but not the only way) to do template stuff
Last edited on
unfortunately i need to have two different files.Any other way i can do it?
If your compiler doesn't support the export keyword, no. There is no other way.
Why do you need separate H and CPP files?

One alternative is:

As you need a llist<int> and a llist<char>
Add the following explicit instantiation commands at the end of the llist.cpp file:

1
2
template class llist<int>;
template class llist<char>;


you obviously will have to make sure the cpp file gets compiled as well.

ok,that worked but now i get [Linker error] undefined reference to `operator<<(std::ostream&, llist<char>&)'

for this function:

1
2
3
4
5
6
7
8
9
10
11
12
template <class itemtype> 
std::ostream& operator<<(std::ostream &output,llist<itemtype> &l)
{  
        typename llist<itemtype>::nodetype *cur;
        cur=l.first;
        while(cur!=0)
        {
           output<<cur->item<<"|";
           cur=cur->next;
           }
        return output;
}   


any help is appreciated
updated code:

header:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#ifndef LList_h_
#define LList_h_
#include <iostream>
using namespace std;
template<class itemtype> 
class llist
{
template <itemtype>      
friend ostream& operator<<(ostream & , const llist&);      
      private:     
      struct nodetype
      {
      itemtype item;
      nodetype *next;
      };
      nodetype *first, *last;      
      public:
             llist();
             void firstinsert(itemtype);
             void frontinsert(itemtype);
             void endinsert(itemtype);
             void inorderinsert(itemtype);
             bool search(itemtype);
             bool Delete (itemtype); 
             bool listempty();
             itemtype firstitem();
             itemtype lastitem();
             ~llist();
};
#endif 


implementation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include "LList.h"
#include<iostream>
template <class itemtype>
llist<itemtype>::llist()
{  
             
   first=last=0;
}
template <class itemtype>
void llist<itemtype>::firstinsert(itemtype x)
{
     first= new nodetype;
     last= first;
     first->item =x;
     first->next = 0;
}
template <class itemtype>
void llist<itemtype>::frontinsert(itemtype x)
{
     nodetype *newnode;
     newnode= new nodetype;
     newnode->item =x;
     newnode->next=first;
     first=newnode;
}
template <class itemtype>
void llist<itemtype>::endinsert(itemtype x)
{
     nodetype *newnode;
     newnode= new nodetype;
     newnode->item =x;
     newnode->next=0;
     last->next=newnode;
     last=newnode;
}
template <class itemtype>
void llist<itemtype>::inorderinsert(itemtype x)
{
     nodetype *cur;
     nodetype *prev;
     
     nodetype *newnode;
     newnode= new nodetype;
     newnode->item =x;
     newnode->next=0;
     if(x<=first->item)
     {
       newnode->next=first;
       first=newnode;
     }
     else if (x>=last->item)
     {
      last->next=newnode;
     last=newnode;
     }
     else
     {
         prev=first;
         cur=first->next;
         while(x>cur->item)
         {
          prev=cur;
          cur=cur->next;
          }
     }
}
template <class itemtype>
bool llist<itemtype>::listempty()
{
return(first==0);
}
template <class itemtype>
itemtype llist<itemtype>::firstitem()
{
return first->item;
}
template <class itemtype>
itemtype llist<itemtype>::lastitem()
{
return last->item;
}
template <class itemtype>
bool llist<itemtype>::search(itemtype x)
{
     nodetype *cur;
     cur=first;
     while ((cur!=0)&&(x!=cur->item))
     {
           cur=cur->next;
     }
     return(cur!=0);
}
template <class itemtype>
llist<itemtype>::~llist()
{
     nodetype *delnode;
     while(first!=0)
     {
       delnode=first;
       first=first->next;
       delete delnode;
     }
}
template <class itemtype>
bool llist<itemtype>::Delete (itemtype x)
{
     nodetype *cur, *prev;
     nodetype *delnode;
     prev=0;
     cur=first;
      while ((cur!=0)&&(x!=cur->item))
     { 
            prev=cur;
            cur=cur->next;
            if(cur==0)
              return 0;
            else
                delnode=cur;
                if(prev==0)
                {   
                    first=first->next;
                }
                else
                {
                prev->next=cur->next;
                if (cur==last)
                   last=prev;
                }
                delete delnode;
                return 1;
     }
}
template <class itemtype> 
ostream& operator<<(ostream &output,llist<itemtype> const&l)
{          

        typename llist<itemtype>::nodetype *cur;
        cur=l.first;
        while(cur!=0)
        {
           output<<cur->item<<"|";
           cur=cur->next;
           }
        return output;
}
template class llist<int>;
template class llist<char>;


main:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "LList.h"
#include<iostream>
using namespace std;
int main()
{
    llist<int> i;
    llist<char> c;
    
    i.firstinsert(1);
    i.frontinsert(2);
    i.endinsert(4);
    i.inorderinsert(3);
    
    c.firstinsert('c');
    c.frontinsert('a');
    c.endinsert('r');
    c.inorderinsert('t');
    
    cout<<c<<endl;
    cout<<i<<endl;
    
    
    system("pause");
    return 0;
}


help is still appreciated
Last edited on
You explicitly instantiate the operator << function the same way as you did before.
(Note: I tend to use template <typename X> rather than template <class X> )

The header file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef LList_h_
#define LList_h_

#include <iostream>
//using namespace std;

template<class itemtype>
class llist
{
    // NOTE: GG has changed the way this friend function has been declared
    template <typename T>
    friend std::ostream& operator<<(std::ostream & , const llist<T>&);

private:
    struct nodetype
    {
        itemtype item;
        nodetype *next;
    };
    nodetype *first, *last;
public:
    llist();
    void firstinsert(itemtype);
    void frontinsert(itemtype);
    void endinsert(itemtype);
    void inorderinsert(itemtype);
    bool search(itemtype);
    bool Delete (itemtype);
    bool listempty();
    itemtype firstitem();
    itemtype lastitem();
    ~llist();
};
#endif 


The implementation file
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include "LList.h"

#include<iostream>
using namespace std;

template <class itemtype>
llist<itemtype>::llist()
{
    first = last = 0;
}

template <class itemtype>
void llist<itemtype>::firstinsert(itemtype x)
{
    first = new nodetype;
    last = first;
    first->item = x;
    first->next = 0;
}

template <class itemtype>
void llist<itemtype>::frontinsert(itemtype x)
{
    nodetype *newnode;
    newnode = new nodetype;
    newnode->item = x;
    newnode->next = first;
    first = newnode;
}

template <class itemtype>
void llist<itemtype>::endinsert(itemtype x)
{
    nodetype *newnode;
    newnode = new nodetype;
    newnode->item = x;
    newnode->next = 0;
    last->next = newnode;
    last = newnode;
}

template <class itemtype>
void llist<itemtype>::inorderinsert(itemtype x)
{
    nodetype *cur;
    nodetype *prev;
    nodetype *newnode;
    newnode = new nodetype;
    newnode->item = x;
    newnode->next = 0;
    if (x <= first->item)
    {
        newnode->next = first;
        first = newnode;
    }
    else if (x >= last->item)
    {
        last->next = newnode;
        last = newnode;
    }
    else
    {
        prev = first;
        cur = first->next;
        while (x > cur->item)
        {
            prev = cur;
            cur = cur->next;
        }
    }
}

template <class itemtype>
bool llist<itemtype>::listempty()
{
    return(first == 0);
}

template <class itemtype>
itemtype llist<itemtype>::firstitem()
{
    return first->item;
}

template <class itemtype>
itemtype llist<itemtype>::lastitem()
{
    return last->item;
}

template <class itemtype>
bool llist<itemtype>::search(itemtype x)
{
    nodetype *cur;
    cur = first;
    while ((cur != 0) && (x != cur->item))
    {
        cur = cur->next;
    }
    return(cur != 0);
}

template <class itemtype>
llist<itemtype>::~llist()
{
    nodetype *delnode;
    while (first != 0)
    {
        delnode = first;
        first = first->next;
        delete delnode;
    }
}

template <class itemtype>
bool llist<itemtype>::Delete (itemtype x)
{
    nodetype *cur, *prev;
    nodetype *delnode;
    prev = 0;
    cur = first;
    while ((cur != 0) && (x != cur->item))
    {
        prev = cur;
        cur = cur->next;
        if (cur == 0)
            return 0;
        else
            delnode = cur;
        if (prev == 0)
        {
            first = first->next;
        }
        else
        {
            prev->next = cur->next;
            if (cur == last)
                last = prev;
        }
        delete delnode;
        return 1;
    }
    return false; //NOTE: This function should return  a value - this line added by GG
}

template <class T>
ostream& operator<<(std::ostream &output, llist<T> const&l)
{
    typename llist<T>::nodetype *cur;
    cur = l.first;
    while (cur != 0)
    {
        output << cur->item << "|";
        cur = cur->next;
    }
    return output;
}

/************************************************/
template class llist<int>;
template class llist<char>;

template ostream& operator<< (ostream &output, llist<int> const&l); //<= See here
template ostream& operator<< (ostream &output, llist<char> const&l);//<= See here
Last edited on
im not using GG,im using Dev. Anyway i can do it with that? Because i tried this and im still getting more errors than needed.
GG = GuestGulkan
works for me (using Dev c++)

Not tried using MSVC
Ah,sorry dude. i typed in what you did. Im still getting the same errors

specifically:
[Linker error] undefined reference to `operator<<(std::ostream&, llist<char> const&)'
[Linker error] undefined reference to `operator<<(std::ostream&, llist<int> const&)'

header
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#ifndef LList_h_
#define LList_h_
#include <iostream>
template<class itemtype> 
class llist
{
template <typename t>      
friend std::ostream& operator<<(std::ostream & , const llist<t>&);      
      private:     
      struct nodetype
      {
      itemtype item;
      nodetype *next;
      };
      nodetype *first, *last;      
      public:
             llist();
             void firstinsert(itemtype);
             void frontinsert(itemtype);
             void endinsert(itemtype);
             void inorderinsert(itemtype);
             bool search(itemtype);
             bool Delete (itemtype); 
             bool listempty();
             itemtype firstitem();
             itemtype lastitem();
             ~llist();
};
#endif 


implementation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
#include "LList.h"
#include<iostream>
template <class itemtype>
llist<itemtype>::llist()
{  
             
   first=last=0;
}
template <class itemtype>
void llist<itemtype>::firstinsert(itemtype x)
{
     first= new nodetype;
     last= first;
     first->item =x;
     first->next = 0;
}
template <class itemtype>
void llist<itemtype>::frontinsert(itemtype x)
{
     nodetype *newnode;
     newnode= new nodetype;
     newnode->item =x;
     newnode->next=first;
     first=newnode;
}
template <class itemtype>
void llist<itemtype>::endinsert(itemtype x)
{
     nodetype *newnode;
     newnode= new nodetype;
     newnode->item =x;
     newnode->next=0;
     last->next=newnode;
     last=newnode;
}
template <class itemtype>
void llist<itemtype>::inorderinsert(itemtype x)
{
     nodetype *cur;
     nodetype *prev;
     
     nodetype *newnode;
     newnode= new nodetype;
     newnode->item =x;
     newnode->next=0;
     if(x<=first->item)
     {
       newnode->next=first;
       first=newnode;
     }
     else if (x>=last->item)
     {
      last->next=newnode;
     last=newnode;
     }
     else
     {
         prev=first;
         cur=first->next;
         while(x>cur->item)
         {
          prev=cur;
          cur=cur->next;
          }
     }
}
template <class itemtype>
bool llist<itemtype>::listempty()
{
return(first==0);
}
template <class itemtype>
itemtype llist<itemtype>::firstitem()
{
return first->item;
}
template <class itemtype>
itemtype llist<itemtype>::lastitem()
{
return last->item;
}
template <class itemtype>
bool llist<itemtype>::search(itemtype x)
{
     nodetype *cur;
     cur=first;
     while ((cur!=0)&&(x!=cur->item))
     {
           cur=cur->next;
     }
     return(cur!=0);
}
template <class itemtype>
llist<itemtype>::~llist()
{
     nodetype *delnode;
     while(first!=0)
     {
       delnode=first;
       first=first->next;
       delete delnode;
     }
}
template <class itemtype>
bool llist<itemtype>::Delete (itemtype x)
{
     nodetype *cur, *prev;
     nodetype *delnode;
     prev=0;
     cur=first;
      while ((cur!=0)&&(x!=cur->item))
     { 
            prev=cur;
            cur=cur->next;
            if(cur==0)
              return 0;
            else
                delnode=cur;
                if(prev==0)
                {   
                    first=first->next;
                }
                else
                {
                prev->next=cur->next;
                if (cur==last)
                   last=prev;
                }
                delete delnode;
                return 1;
     }
}
template <class t> 
std::ostream& operator<<(std::ostream &output,llist<t> const&l)
{          

        typename llist<t>::nodetype *cur;
        cur=l.first;
        while(cur!=0)
        {
           output<<cur->item<<"|";
           cur=cur->next;
           }
        return output;
}
template class llist<int>;
template class llist<char>;

template std::ostream& operator<< (std::ostream &output, llist<int> const&l);
template std::ostream& operator<< (std::ostream &output, llist<char> const&l);


any help is appreciated
Last edited on
never mind,got it
Just out of interest - what was the problem?
Topic archived. No new replies allowed.