(C++) Function name as template argument

Started by
7 comments, last by ToohrVyk 20 years, 1 month ago
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

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;}
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

Why not just use Boost.Function and accept a functor during construction?
--God has paid us the intolerable compliment of loving us, in the deepest, most tragic, most inexorable sense.- C.S. Lewis
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]
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
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]
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

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.

This topic is closed to new replies.

Advertisement