Mediator Pattern Help!

Started by
0 comments, last by BitMaster 9 years, 11 months ago

Hey all,

I'm writing a Mediator class in C++ and am having trouble with a part of it. I've done this before in C# (which was really easy) and trying to do the same thing in C++ is kicking my butt. I have a std::map that contains a std::string for the key and a std::vector<> for the value. The idea being any number of functions/methods can be registered under any number of keys and all said functions/methods can be invoked with one call.

I'm having two primary problems: 1, I can't figure out how to get both functions AND class methods into the std::map. Currently I'm using:


typedef std::function<void(void* Object)> FunctionDef;

I have a Register method in my Mediator class that takes a std::string for the key and a FunctionDef for the value. So far this works fine for functions but I can't get it to work with class methods.

And 2; I have an Unregister method in my Mediator class that takes the same inputs and removes the appropriate function from the appropriate key. Or, at least, it's supposed too.


template<class T>
static void Unregister(std::string Key, T Function)
{
		if (MediatorMap.count(Key) != 0)
		 {
			FunctionDef Func = Function;
			for (std::vector<FunctionDef>::iterator It = MediatorMap[Key].begin();
				It != MediatorMap[Key].end();
				++It)
			 {
				 if ((*It).target_type().name() == Func.target_type().name())
				{
					std::cout << "1" << std::endl;

					std::cout << (*It).target<T>() << " == " << Func.target<T>() << " ?? \n";
					if ((*It).target<T>() == Func.target<T>())
					{
						std::cout << "2" << std::endl;
					}
				}
			}

			if (MediatorMap[Key].size() == 0)
			{
				MediatorMap.erase(MediatorMap.find(Key));
			}
		}
	}

This is basicaly just testing code ATM. The problem seems to be, and mind you I can only test this with functions, that whatever info is provided by .target<T>() (I'm guessing the pointer) never matches, even when sending the same function.

I admit to not really being sure of what I'm doing. This is new territory for me and my C++ is a little rusty. Any help would be appreciated.

Advertisement

Regarding 1):

Instead of trying to assign a member function pointer (which will obviously not work because member functions have a different signature), assign a lambda:

MyObject obj;
//...
FunctionDef myFunction = [&] () { obj.memberFunctionToCall(); };

Warning: there are a lot of caveats regarding what to capture in the lambda and how to do it regarding the lifetime of the objects involved. Unless you know what you are doing exactly I would strongly recommend you post some use case examples and how you intend to use this.

Regarding 2):

That is impossible. As the documentation says: any non-empty std::function objects will always compare non-equal. Even if they were created using the same source-function. Even if they are copies of each other.

The typical way to solve this is returning some kind of Connection-object which uniquely identifies that particular connection. See for example how boost::signals2 works.

This topic is closed to new replies.

Advertisement