Jump to content
  • Advertisement

Archived

This topic is now archived and is closed to further replies.

ToohrVyk

(C++) Function name as template argument

This topic is 5232 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I would like to know if it''s possible to pass the name of a member function as a template argument. The case is the following : I''m creating a single-linked list that has some additional features with regards to std::slist, and I would like to have a templated "map" function which receives as a template argument the member function of the stored object that is to be called. For instance, a call to map<thisFunction> would call Object.ThisFunction( ) on all objects. For simplicity''s sake, I assume all such argument functions are of type void (void).
template<typename Stored>
class mySlist {
[slist implementation]
public:

template<functionname Mapped>
void map( void ) {
for( temp = m_listhead; temp; temp = temp->next ) {temp->contents.Mapped( ); }
};
Thank you for your time.

Victor Nicollet, INT13 game programmer

Share this post


Link to post
Share on other sites
Advertisement
I don''t think function names are valid template parameters. However, function pointers to functions with external linkage are valid template parameters.


#include <iostream>

template < void (* function)(void) >
class SomeClass {
public:
SomeClass() {
function();
}
};

void hug_me(void) {
std::cout << "Hug me!" << std::endl;
}

void kill_dinosaur(void) {
std::cout << "Kill the dinosaur!" << std::endl;
}

int main(int, char **) {
SomeClass<hug_me> a;
SomeClass<kill_dinosaur> b;
return 0;
}

Share this post


Link to post
Share on other sites
So something like this should work, shouldn''t it?


void t_doFunc( Object * O ) { O->Func( ); }

template<typename Stored>
class mySlist {
[slist implementation]
public:
template<void (*Mapped) (Stored*)>
void map( void ) {for( temp = m_listhead; temp; temp = temp->next ) { Mapped( temp->contents ); }
}
};

[later...]
mySlist<Object> myList;
myList.map<t_dofunc>( );


I still feel this is unnecessary verbose, but still. Does it also work with static functions?



Victor Nicollet, INT13 game programmer

Share this post


Link to post
Share on other sites
That looks fine, syntax-wise. It should work with static member functions or any other kind of function that matches the signature of the function pointer template parameter.

Style-wise it might just be easier to use a typename template parameter and pass the function as a parameter. As in:

template<typename fn_type>
void map(fn_type fn) {
for( temp = m_listhead; temp; temp = temp->next ) {
fn( temp->contents );
}
}

This takes better advantage of inlining in some circumstances and allows you to use function objects as well as function pointers.

edit: On second thought: why not just use std::for_each() ?

[edited by - SiCrane on February 26, 2004 5:21:17 PM]

Share this post


Link to post
Share on other sites
This is somewhat close to what you wanna do, I guess...


#include <iostream>

template <typename T>
class mySlist
{
public:
mySlist() : _t() {};
void map(void (T::* mfp)()) { ((_t).*mfp)(); }
private:
T _t;
};

class Stored
{
public:
void Mapped() { std::cout << "This is a mapped call..." << std::endl; }
};

int main()
{
mySlist<Stored> a;

a.map(Stored::Mapped);
return 0;
}


(you''ll have to make it work for a slinked list yourself though)

btw, you might wanna look into..., dammit SiCrane you beat me to it... :-)

Also check out binder* and mem_fun_* in STL

-- pal

Share this post


Link to post
Share on other sites
template< void (*function)(void) > class FunctionCaller
{
public:
CallTheFunction( void ) { function(); }
};

void SayPie( void );

FunctionCaller< SayPie > PieCaller;
PieCaller.CallTheFunction();


Should also work if you expect this map functino to allways use the same function name... If you planned on taking a type of function in numerous places, creating a common typedef would shorten your typing. Aka:

typedef void (*MapFunc)(void);

template< MapFunc Mapped > void map ( void ) { /*....*/ }


-Mike

[edited by - MaulingMonkey on February 27, 2004 2:32:02 AM]

Share this post


Link to post
Share on other sites
Thank you, the solution _pal_ suggested worked just fine.

The problem with std::for_each is that I don''t have any iterators to work with, only an internal linked list structure.

Also, if you wonder why I''m creating my own slist instead of using the stl one (and I know this sound like reinventing the wheel) I currently need to be able to memcopy the list to a file, or vice versa, during the save process. This means I cannot rely on the stl implementations because
1°/ Compilation will be done using three different compilers for three different platforms, but save files must be exchangeable between the platforms.
2°/ I need to run through all pointers and convert them to a save/loadable state, including the pointers used internally by the SList

And also...
3°/ I know at compile-time the maximum number of objects in the list, but I''m sure this one can be solved using STL.

Victor Nicollet, INT13 game programmer

Share this post


Link to post
Share on other sites
Writing a forward iterator class for a singly linked list is easy. As data all you need is a pointer to your node and then overload operator++() to get the next node. Once you have a compatible forward iterator you should be able to use std::for_each() on your linked list class just fine.

Share this post


Link to post
Share on other sites

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!