Jump to content

  • Log In with Google      Sign In   
  • Create Account


Templates causing linker errors.


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
5 replies to this topic

#1 blueshogun96   Crossbones+   -  Reputation: 811

Like
0Likes
Like

Posted 21 May 2014 - 04:05 AM

I recently converted my linked list code from C to C++ using templates.  Afaik, my functions are clearly defined, but my compiler (XCode) still doesn't like it.  Here's an example function definition:

template <class T>
class node_t
{
 node_t();
 virtual ~node_t();

public:
 T data;
 node_t<T>* next;
};

template <class T>
void list_add_end( node_t<T>** list, T data );

And this is a usage example:

class base_process_t
{
 base_process_t();
 virtual ~base_process_t();

public:
 virtual void foo1() PURE;
 virtual void foo2() PURE;
};

list_add_end<base_process_t*>( &process_list, new base_process_t() );

This all compiles fine, but doesn't link.  The typical error I get is:

 

Undefined symbols

"list_add_end<base_process_t*>( node_t<base_process_t*>**, base_process_t* )" referenced from (blah blah blah)

 

This isn't really making any sense to me.  Is it because of my classes using virtual functions by chance?  This is my first time attempting to do this, and after all the years I've been using C++, I can't believe I'm stumped on a seemingly minuscule problem, and I have the feeling I'm going to feel really stupid once I figure this out.  This sucks.  Any ideas?  Thanks.

 

Shogun


Follow Shogun3D on the official website: http://shogun3d.net

 

blogger.png twitter.png tumblr_32.png facebook.png


Sponsor:

#2 Juliean   GDNet+   -  Reputation: 2229

Like
0Likes
Like

Posted 21 May 2014 - 04:34 AM

template <class T>
void list_add_end( node_t<T>** list, T data );

Where is the definition of that function? The reason for this error could be that it is simply missing.



#3 blueshogun96   Crossbones+   -  Reputation: 811

Like
1Likes
Like

Posted 21 May 2014 - 04:37 AM

It's not missing, but I solved the problem though.

 

The template functions needed to be moved from a .cpp to a .inl and the functions needed to be inlined.  Then include the .inl instead of .hpp, and that solved everything.

 

Shogun.


Follow Shogun3D on the official website: http://shogun3d.net

 

blogger.png twitter.png tumblr_32.png facebook.png


#4 Rattrap   Members   -  Reputation: 1497

Like
0Likes
Like

Posted 21 May 2014 - 04:44 AM

The template functions needed to be moved from a .cpp to a .inl and the functions needed to be inlined.  Then include the .inl instead of .hpp, and that solved everything.


Yup. Templates need to be contained in a header file, not a cpp, as you discovered. This can cause some headache if you end up with circular dependences that would normally just be solved by separating the definitions from the declarations in a h/CPP pairing.

#5 SeanMiddleditch   Members   -  Reputation: 3868

Like
1Likes
Like

Posted 21 May 2014 - 07:58 PM

The template functions needed to be moved from a .cpp to a .inl and the functions needed to be inlined.  Then include the .inl instead of .hpp, and that solved everything.


You don't _strictly_ need this. The only rule is that the linker can find a definition of your template. You could keep your template in a .cpp file so long as the .cpp knows exactly what to instantiate explicitly (e.g. if you only use <int> and <float> with your template, declare those as 'extern' and then explicitly instantiate them in your .cpp file with the template code). This is less flexible but makes things compile faster if used well and appropriately in larger projects, which may be of interest.

#6 NightCreature83   Crossbones+   -  Reputation: 2672

Like
2Likes
Like

Posted 22 May 2014 - 02:44 AM

template <class T>
void list_add_end( node_t<T>** list, T data );

If all you do is modify what the list pointer needs to point at please write this in the C++ way, which looks like this:

template <class T>
void list_add_end( node_t<T>*& list, T data );

Also means you don't have to write your pointer modification code like this anymore:

node_t<t>* newNode = new node_t<T>();
*list = &newNode;
 
//instead you can just write this
node_t<t>* newNode = new node_t<T>();
list = newNode;

Edited by NightCreature83, 22 May 2014 - 02:55 AM.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, Mad Max




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS