Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > template compile errors

Reply
Thread Tools

template compile errors

 
 
Thomi Richards
Guest
Posts: n/a
 
      10-13-2004
Hi,


I'm trying to create a simple stack class using C++ and templates.
Everything works well and good if I amke the class totally inline.
However, as soon as I try to seperate the class into a .h and a .cpp
file, gcc throws some strange linking errors.

Compiling like this:

gcc test.cpp stackList.cpp -lstdc++ -o test

produces these errors:

/tmp/ccCJLrbl.o(.text+0x84): In function `main':
: undefined reference to `Stack<int>::Stack[in-charge]()'
/tmp/ccCJLrbl.o(.text+0x101): In function `main':
: undefined reference to `Stack<int>:ush(int)'
/tmp/ccCJLrbl.o(.text+0x10c): In function `main':
: undefined reference to `Stack<int>::size() const'
/tmp/ccCJLrbl.o(.text+0x18b): In function `main':
: undefined reference to `Stack<int>::empty() const'
/tmp/ccCJLrbl.o(.text+0x19c): In function `main':
: undefined reference to `Stack<int>::size() const'
/tmp/ccCJLrbl.o(.text+0x1aa): In function `main':
: undefined reference to `Stack<int>:op()'
/tmp/ccCJLrbl.o(.text+0x20f): In function `main':
: undefined reference to `Stack<int>::~Stack [in-charge]()'
/tmp/ccCJLrbl.o(.text+0x229): In function `main':
: undefined reference to `Stack<int>::~Stack [in-charge]()'
collect2: ld returned 1 exit status


I'm tearing my hair out... why would it not work in seperate files? My
class definition is something like this:

template <class T>
class Stack
{
private:
StackNode<T> *stackHead;
/// The number of elements on the stack. It's easier to keep count
/// of them here than to count them every time we need them.
unsigned int stackSize;
protected:
public:
/// Default constructor: set the stackSize to be 0.
Stack(void);

/// Default destructor: clean up any memory allocated.
~Stack(void);
/// push: push an item onto the stack, and incrememt the size.
bool push(T item);

/// pop: return the topmost element from the stack, removing it
from the stack at the same time:
T pop(void);

/// size: returns how many items are on the stack:
unsigned int size(void) const;
/// empty: return true if the stack is empty:
bool empty(void) const;
/// full: return true if the stack is full: - for a linked list
implementation, this can be safely ignored:
bool full(void) const;

};


and the code for a single method for the above class looks like this:

template <class T> bool Stack<T>:ush(T item)
{
if (full())
return false;

StackNode<T> *node = new StackNode<T> (item);
node->Head = stackHead;
stackHead = node;
stackSize++;

return true;
}

I've been following the C++ language tutorial, and a few books I own
at home. It looks like I'm doing everything properly... Can anyone
shed some light on this?


Thanks,
 
Reply With Quote
 
 
 
 
David Lindauer
Guest
Posts: n/a
 
      10-13-2004


Thomi Richards wrote:

> Hi,
>
> I'm trying to create a simple stack class using C++ and templates.
> Everything works well and good if I amke the class totally inline.
> However, as soon as I try to seperate the class into a .h and a .cpp
> file, gcc throws some strange linking errors.
>
> Compiling like this:
>
> gcc test.cpp stackList.cpp -lstdc++ -o test
>
> produces these errors:
>
> /tmp/ccCJLrbl.o(.text+0x84): In function `main':
> : undefined reference to `Stack<int>::Stack[in-charge]()'
> /tmp/ccCJLrbl.o(.text+0x101): In function `main':
> : undefined reference to `Stack<int>:ush(int)'
> /tmp/ccCJLrbl.o(.text+0x10c): In function `main':
> : undefined reference to `Stack<int>::size() const'
> /tmp/ccCJLrbl.o(.text+0x18b): In function `main':
> : undefined reference to `Stack<int>::empty() const'
> /tmp/ccCJLrbl.o(.text+0x19c): In function `main':
> : undefined reference to `Stack<int>::size() const'
> /tmp/ccCJLrbl.o(.text+0x1aa): In function `main':
> : undefined reference to `Stack<int>:op()'
> /tmp/ccCJLrbl.o(.text+0x20f): In function `main':
> : undefined reference to `Stack<int>::~Stack [in-charge]()'
> /tmp/ccCJLrbl.o(.text+0x229): In function `main':
> : undefined reference to `Stack<int>::~Stack [in-charge]()'
> collect2: ld returned 1 exit status
>
> I'm tearing my hair out... why would it not work in seperate files? My
> class definition is something like this:
>
> template <class T>
> class Stack
> {
> private:
> StackNode<T> *stackHead;
> /// The number of elements on the stack. It's easier to keep count
> /// of them here than to count them every time we need them.
> unsigned int stackSize;
> protected:
> public:
> /// Default constructor: set the stackSize to be 0.
> Stack(void);
>
> /// Default destructor: clean up any memory allocated.
> ~Stack(void);
> /// push: push an item onto the stack, and incrememt the size.
> bool push(T item);
>
> /// pop: return the topmost element from the stack, removing it
> from the stack at the same time:
> T pop(void);
>
> /// size: returns how many items are on the stack:
> unsigned int size(void) const;
> /// empty: return true if the stack is empty:
> bool empty(void) const;
> /// full: return true if the stack is full: - for a linked list
> implementation, this can be safely ignored:
> bool full(void) const;
>
> };
>
> and the code for a single method for the above class looks like this:
>
> template <class T> bool Stack<T>:ush(T item)
> {
> if (full())
> return false;
>
> StackNode<T> *node = new StackNode<T> (item);
> node->Head = stackHead;
> stackHead = node;
> stackSize++;
>
> return true;
> }
>
> I've been following the C++ language tutorial, and a few books I own
> at home. It looks like I'm doing everything properly... Can anyone
> shed some light on this?
>
> Thanks,


code for a template doesn't really exist until you instantiate it... in
a very raw sense they are kind of like
macros in that regard. Until you use them, no code or data gets
generated. If you just take part of a group of template definitions and
stick them in a C++ file, no code will be generated in the file, and you
end up with essentially the same problem as if you are working in C and
move all the global #defines into a C language source file, they just
wouldn't be accessible. What happens when you instantiate a template is,
the compiler takes all the structures and functions you have declared
related to the template and tries to make functions out of them, using the
instantiated types instead of the placeholder types you used when you
declared the template. So you can instantiate one template using many
many different types in the course of a single program, but the cost is
that each time you change the types given in the instantiation, the
compiler generates another set of code and data specific to those types.

You might be able to fix this particular problem by instantiating a
template using the <int> type in your source file that you put the
templates in, that may at least cause the functions to get declared so
they will appear at link time. However, that means that for every time
you want to use that template with a different type, you've got to go into
your source file and instantiate it deliberately. Since that really cuts
down on the power of templates dramatically, it is usually recommended you
just group all the template functions and so forth in header files, but of
course that is its own problem since if you are modifying global headers
very often it can force you to recompile large parts of your project on a
regular basis.

David
 
Reply With Quote
 
 
 
 
E. Robert Tisdale
Guest
Posts: n/a
 
      10-13-2004
Thomi Richards wrote:

> I'm trying to create a simple stack class using C++ and templates.
> Everything works well and good if I amke the class totally inline.
> However, as soon as I try to seperate the class into a .h and a .cpp
> file, gcc throws some strange linking errors.
>
> Compiling like this:
>
> gcc test.cpp stackList.cpp -lstdc++ -o test
>
> produces these errors:
>
> /tmp/ccCJLrbl.o(.text+0x84): In function `main':
> : undefined reference to `Stack<int>::Stack[in-charge]()'
> /tmp/ccCJLrbl.o(.text+0x101): In function `main':
> : undefined reference to `Stack<int>:ush(int)'
> /tmp/ccCJLrbl.o(.text+0x10c): In function `main':
> : undefined reference to `Stack<int>::size() const'
> /tmp/ccCJLrbl.o(.text+0x18b): In function `main':
> : undefined reference to `Stack<int>::empty() const'
> /tmp/ccCJLrbl.o(.text+0x19c): In function `main':
> : undefined reference to `Stack<int>::size() const'
> /tmp/ccCJLrbl.o(.text+0x1aa): In function `main':
> : undefined reference to `Stack<int>:op()'
> /tmp/ccCJLrbl.o(.text+0x20f): In function `main':
> : undefined reference to `Stack<int>::~Stack [in-charge]()'
> /tmp/ccCJLrbl.o(.text+0x229): In function `main':
> : undefined reference to `Stack<int>::~Stack [in-charge]()'
> collect2: ld returned 1 exit status
>
>
> I'm tearing my hair out... why would it not work in seperate files?
> My class definition is something like this:
>
> template <class T>
> class Stack
> {
> private:
> StackNode<T> *stackHead;
> /// The number of elements on the stack. It's easier to keep count
> /// of them here than to count them every time we need them.
> unsigned int stackSize;
> protected:
> public:
> /// Default constructor: set the stackSize to be 0.
> Stack(void);
>
> /// Default destructor: clean up any memory allocated.
> ~Stack(void);
> /// push: push an item onto the stack, and incrememt the size.
> bool push(T item);
>
> /// pop: return the topmost element from the stack, removing it
> from the stack at the same time:
> T pop(void);
>
> /// size: returns how many items are on the stack:
> unsigned int size(void) const;
> /// empty: return true if the stack is empty:
> bool empty(void) const;
> /// full: return true if the stack is full: - for a linked list
> implementation, this can be safely ignored:
> bool full(void) const;
>
> };
>
>
> and the code for a single method for the above class looks like this:
>
> template <class T> bool Stack<T>:ush(T item)
> {
> if (full())
> return false;
>
> StackNode<T> *node = new StackNode<T> (item);
> node->Head = stackHead;
> stackHead = node;
> stackSize++;
>
> return true;
> }


Since you didn't tell us, I'll suppose that
you moved the function template definitions
from your stackList.h header file
to your stackList.cpp source file and that
you include'd the stackList.h header file
but *not* the stackList.cpp source file
in your test.cpp source file.

Please allow me to ask a simple question,

"How does the C++ compiler know
where to find the function template definitions
so that it can instantiate them
when it is compiling test.cpp?"

> I've been following the C++ language tutorial,
> and a few books I own at home.


> info gcc 'C++ extensions' 'Template Instantiation'


> It looks like I'm doing everything properly...
> Can anyone shed some light on this?


If you know all of the template functions that you need.
you can instantiate the template functions *explicitly*:

template Stack<int>::Stack(void);
template std::bool Stack<int>:ush(int);
template size_t Stack<int>::size(void) const;
template std::bool Stack<int>::empty(void) const;
template int Stack<int>:op(void);
template void Stack<int>::~Stack(void);

right after the function template definitions
in your stackList.cpp source file.
 
Reply With Quote
 
David Hilsee
Guest
Posts: n/a
 
      10-13-2004
"Thomi Richards" <> wrote in message
news: om...
> Hi,
>
>
> I'm trying to create a simple stack class using C++ and templates.
> Everything works well and good if I amke the class totally inline.
> However, as soon as I try to seperate the class into a .h and a .cpp
> file, gcc throws some strange linking errors.
> [...]
> I'm tearing my hair out... why would it not work in seperate files? My
> class definition is something like this:
> [...]


See the FAQ (http://www.parashift.com/c++-faq-lite/), section 34 ("Container
classes and templates"), question 12 ("Why can't I separate the definition
of my templates class from it's declaration and put it inside a .cpp file?")
and the related questions that follow.

--
David Hilsee


 
Reply With Quote
 
Thomi Richards
Guest
Posts: n/a
 
      10-13-2004
Ahh,

Thanks for that.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
template template parameter compilation errors!!! aaragon C++ 6 03-23-2008 06:16 PM
cant compile on linux system.cant compile on cant compile onlinux system. Nagaraj C++ 1 03-01-2007 11:18 AM
Explicit template instantiation from template function doesn't compile? Fernando Cuenca C++ 4 09-06-2004 04:06 PM
Errors, errors, errors Mark Goldin ASP .Net 2 01-17-2004 08:05 PM
Re: A Newbie Question about template template template Chris Theis C++ 2 07-24-2003 09:42 AM



Advertisments
 



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