Skip to main content
gamedev.net
🔒 Locked

pointer to Member Function

Started by bilsa 8 replies 450+ views
Original Post
bilsa
bilsa
Ok, I'm making a templated Manager class, since I heavily use managers in my game engine that I am making. Anyway I have found myself using std containers for the Managers I am using. Now many of my managers have some common stuff like, AddWindow, AddSystem, AddSomethinElse. So I was thinking of making a templated Manager Class that has these functionalitys. Ok, So what I first figured was something like this:
template <class Type>
class Manager {
public:
//Some General functions for a manager... something along this:

AddItem(Type);
RemoveItem(Type);
RemoveAll();
Type GetItem();
privat:
//here comes a container of some sort

};
But soon I realized that that won't work. We want to be able to choose what type of container we want our manager to use. But hey, now I realized that the AddItem will be different for some containers, eg. adding an item to a std::map is different from adding an item to a std::list. Well, so what I though about was applying some kind of Traits or some kind of Container Policy that will take care of the common functions for a given container. Ok, so my next design was something along this: Manager.h
template <class ContainerPolicy>
class Manager : public ContainerPolicy {
public:
	Manager();
	~Manager();

private:
};
Now when creating a Manager I will have to choose a ContainerPolicy class to derive from, the policy that will take care of the desired functions. (AddItem, RemoveItem...) ContainerPolicy.h
   
template <
	class Type, 
	void (std::list::*pInsertFn)(const Type& obj) = &std::list::push_back 
>
struct ListContainer {
protected:
	std::list<Type> m_Container;
public:
	void AddItem(const Type& obj) {
		(m_Container.*pInsertFn)(obj);
	}
	void RemoveItem(const Type& obj) {
		
	}
	int RemoveAll() {
		m_Container.clear();
		return m_Container.empty();
	}
	Type& GetItem(int nPos) {
		for(LI iterList = m_Container.begin(); iterList != m_Container.end(); ++iterList) {
			if(nPos == 0) return *iterList;
		}
	}
	typedef class std::list<Type>::const_iterator LI;
};
The ListContainer will take A type and a functionpointer:
ListContainer<int, /*Pointer to std container member function*/> LI_CONTAINER_1;

//but since we have a default function given, this will be enough:


ListContainer<char*> LI_CONTAINER_2;
The problem I was having was the Member function pointer, but we'll get to that later... oh well, the ListContainer alone isn't much to cheer about. But together with the Manager class that would be not so bad. Think about this:
Manager<ListContainer<int> >  MyIntManager;


/*This will create a Manager that uses a list as a container and operates on int's only. So Now we can use this:

MyIntManager.AddItem(5);
MyIntManager.AddItem(10);
MyIntManager.AddItem(2);
MyIntManager.RemoveItem(2); //removes the second item in the list..
the resulting list will contain the following
5
2
*/
Well, you may say this is exactly what the List container does! And yes, that is exactly the same as the pure list functions do... But hey, as I stated I use many managers of similar functionalitys ... so to create a new Manager all I have to do is:
   
class MyNewManager : public Manager<ListContainer<int> >{
};


/*Now whenever I would want to use my Manager class, of course to derive from I would do like this:*/


class CImageManager : public Manager<ListContainer<CImage*> > {
}


/*And hey... now I got a CImageManager that can do the following:
AddItem, RemoveItem, RemoveAll ...*/
And I don't need to revrite the code for it, nice huh Ok, back to the problem I had about the Pointer to member function. The pointer to member function looked like this:
template <
	class Type, 
	/* the pointer to member function */ void (std::list::*pInsertFn)(const Type& obj) = &std::list::push_back 
>
It is supposed to point to the std::list:ush_back function for any given type. But the code gave me this error: cannot convert void(__thiscall std::list::*)(const T1&) to void(__thiscall std::list::*)(const int&) And the problem was solved like this: (thx to SiCrane)
template <
	class Type, 
	/* the pointer to member function */ void (std::list<Type>::*pInsertFn)(const Type& obj) = &std::list<Type>::push_back 
>
I had forgotten to add the Type to the list... So the working code of: ContainerPolicy.h
   
template <
	class Type, 
	/* the pointer to member function */ void (std::list<Type>::*pInsertFn)(const Type& obj) = &std::list<Type>::push_back 
>
struct ListContainer {
protected:
	std::list<Type> m_Container;
public:
	void AddItem(const Type& obj) {
		(m_Container.*pInsertFn)(obj);
	}
	void RemoveItem(const Type& obj) {
		
	}
	int RemoveAll() {
		m_Container.clear();
		return m_Container.empty();
	}
	Type& GetItem(int nPos) {
		for(LI iterList = m_Container.begin(); iterList != m_Container.end(); ++iterList) {
			if(nPos == 0) return *iterList;
		}
	}
	typedef class std::list<Type>::const_iterator LI;
};
The Second priblem was that I had : typedef std::list::const_iterator LI; which should be: typedef class std::list::const_iterator LI; Thx for the help guys And for everyone else, If you have read this article then you should be able to finish your own Templated Manager Base class, from the info given here, Good luck guys! /bilsa [edited by - bilsa on January 8, 2004 11:32:58 AM]
Fruny
Fruny
Tried SomeClassWithAContainer<ListContainer<int, &std::list<int>::‍push_front> > ?

A class template (i.e. with unspecified parameters) is not a class, therefore std::list::‍push_front is not a member function, and you can't take its address.

A function object argument might work better.

[edited by - Fruny on January 8, 2004 8:38:06 AM]
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
SiCrane
SiCrane
If I understand what you''re trying to do, then I''d have to say that you''re missing a couple of necessary specializations. Try:

template <class Type,
void (std::list<Type>::*pInsertFn)(const Type& obj) = &std::list<Type>::push_back >
struct ListContainer {
protected:
std::list<Type> m_Container;
public:
void AddItem(const Type& obj) {
(m_Container.*pInsertFn)(obj);
}
int RemoveItem(const Type& obj) { ...
}
};

// Both these should work:

SomeClassWithAContainer<ListContainer<int> > s1;
SomeClassWithAContainer<ListContainer<int, &std::list<int>::push_front> > s2;
bilsa
bilsa
Ok, the original question was anwsered...

but now I have this problem instead:

template <class Type>;
class SomeClass {
public:
void func1() {}
private:
typedef std::list<Type>::const_iterator LI;
};


I'm getting crazy about this when I get the error:

syntax error: missing ';' before identifier 'LI'

I mean, so fucking what?!! I've been using :
typedef std::list::const_iterator LI
fucking dozen of times and there never was any fucking problem! why now?! (soon gonna tear my hair apart...)

okok... I know I'm a newbie...




SiCrane, thank you very much.


[edited by - bilsa on January 8, 2004 9:32:19 AM]

[edited by - bilsa on January 8, 2004 10:31:37 AM]
SiCrane
SiCrane
Two problems I can see:
1) ; after template <class Type>
2) typedef std::list<Type>::const_iterator LI; should be
typedef typename std::list<Type>::const_iterator LI;
Fruny
Fruny
For what it''s worth, I concur

Oh, and bilsa, you shouldn''t have erased your original question, it could have helped other people (ok, I''m fooling myself here, as if anybody ever learns here), but now it''s gone, and our earlier replies are out of context.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Nervo
Nervo
quote:
Original post by Fruny
but now it''s gone, and our earlier replies are out of context.


Tell me about it. I opened the thread a few minutes ago seeing if I could help out or even learn something and then I see a barebones looking template class with both Sicrane and your posts, and I was rather confused.
Well, R2D22U2..
Fruny
Fruny
The original post essentially contained what SiCrane re-posted, except for the last line which was lacking the <int> template parameter of &std::list<int>::‍pushback.

The OP was basically wondering why the compiler wouldn't let him use that as an actual pointer to member.

[edited by - Fruny on January 8, 2004 10:21:52 AM]
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
SiCrane
SiCrane
Actually, he was also missing the <Type> in the template declaration of the class. Before the second template parameter was a templated function template instead of a reference to a function pointer.
bilsa
bilsa
Ok guys, for the ones that wanted to learn something I have posted a walkthrough of what I was doing - hope you like it... erhm, at least find it interesting...

ps. Remember that you can add other containers to the ContainerPolicy... Lets say a map container or a hash map... its all up to you, how many you feel you want to implement.

But remember that this code can be reused over and over in your projects... So I wouldn't say its a waste of time

And I would probabilly make my Managers Singletons as well... but it's all up to you

If you want to learn more about Policy classes... I would recommend "Modern C++ design", a great book.

Or if anyone wants maybe I could fix this thread to a tutorial/article about how to make a Generic Manager class with policys?

Don't know if this is the best method... but it's the best I could think of, but as noted before... I'm a friggin newbie... (often ending up tearing his hair apart...)

Special thx to SiCrane

[edited by - bilsa on January 8, 2004 11:36:24 AM]

[edited by - bilsa on January 8, 2004 11:39:51 AM]

Topic Locked

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

Sign in to reply to this topic.