Skip to main content
GameDev.net gamedev.net
🔒 Locked

Problem: Function pointer as argument to template class' member function

Started by WhiteCoffee Sep 27, 2008 at 8:43 AM 5 replies 1.1k views
Original Post
WhiteCoffee
WhiteCoffee
I've not used function pointers too much yet, but I've tried it a little and get the idea. Now I do got a problem. I have a class like this: template class CContainer { public : .... void EraseAll( void (__cdecl *DeleteRoutine)(void) ); } DeallocateXFileContent(void); When I try pass this function as a function pointer argument like this.. m_XFileContainer.EraseAll(DeallocatedXFileContent); ...get the compile error: error LNK2001: unresolved external symbol "public: int __thiscall CContainer::EraseAll(void (__cdecl*)(void))" ......... If I do this with an ordinary class, without the template it's no problem. But with this class using the template variable, I get the compile error. I don't get it, how should I change my code to be able to pass the function in the argument list?
rip-off
rip-off
Due to limitations in the majority of popular C++ compilers (or deficiencies in how the standard itself) you cannot implement a template function in a source file, you must do so in a header file.

There are ways around this (e.g. explicit instantiation) but usually it is easiest and most flexible to put the implementation in the header itself.

I'm sort of curious as to how your DeleteRoutines will work, considering you don't pass them any parameters [smile].

It can be easier to use templates for this, rather than an explicit function pointer. This allows you to pass functors and save you from the horrible syntax of function pointers. In fact, if the function is simply applied to every member, consider using non-member functions. By simply implementing an iterator type, with the appropriate begin() and end() functions, and a clear() function:
template <class Value>class Container{public:    // ...    class iterator {       // ...    };    iterator begin();    iterator end();    void clear();};template<class Container, class Functor>void EraseAll(Container &c, Functor f){   std::for_each(c.begin(),c.end(),f);   c.clear();}


Finally, what kind of container is this? Would not a standard container suffice?
dmatter
dmatter
Without working export keyword support then when it comes to using a template the entire class or function definition needs to be in the same translation unit. In other words, make sure you have the definition of EraseAll in the same file that CContainer is declared in.
Zakwayda
Zakwayda
Where is EraseAll() defined?

[Oops, too slow.]
rip-off
rip-off
Quote:
Original post by dmatter
Without working extern keyword support then when it comes to using a template the entire class or function definition needs to be in the same translation unit. In other words, make sure you have the definition EraseAll in the same file that CContainer is declared in.


It doesn't really have to be in the same file, it just needs to be visible. A common approach is to put template implementations into a second header and then include that header just after the class in the primary header file, like so:
// example.htemplate<class T>class Example{    void frobnicate(const T &);};#include "example_impl.h"// example_impl.htemplate<class T>void Example<T>::frobnicate(const T &){    // do some heavy frobnication here}
WhiteCoffee
WhiteCoffee
Okay. I posted only the declarations of the class and functions (the h-file content) in this post. The definitions are in the source file, nothing particular about them though. So I have to put the definition in the header file as well? Or do the full template version that rip-off suggested.

(Of course the DeleteRoutine should have some input parameters.. Just didn't include them in the testing process.)

The container is supposed to store loaded meshes or textures, so I can have many instances just pointing to one entry in the container. I made this class encapsulating the real stl container, (using a map right now, maybe hash map is better), to allow for easy change of container type, maybe some extra functions etc. Maybe this is not the best solution though, but with this thread I just wanted to understand the function pointer rel. templates problem.
dmatter
dmatter
Quote:
Original post by rip-off
It doesn't really have to be in the same file, it just needs to be visible.
Yes sorry, I didn't quite mean exactly what I'd said there - it just needs to be visible from within the same translation unit that makes it concrete.

Quote:
Original post by WhiteCoffee
So I have to put the definition in the header file as well? Or do the full template version that rip-off suggested
Yep, that's it.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.