I'm trying to extend a subject observer pattern to take a function from a class rather than a static function. I've followed juan chopanza EXCELLENT example at Simple Observer Pattern c++11 Now I'd like to pass a class member function as the registered call back rather than a simple function.
I've realized that I can call a class member by using a bind(&class::member,instance) as per the following:
class A {
public:
void A_Bar() { std::cout << "A" << m_nTest << "_bar()" << std::endl; }
void A_Foo(int n) { std::cout << "A" << m_nTest << "_Foo(" << n << ")" << std::endl; }
int m_nTest;
};
int main(int argc, _TCHAR* argv[])
{
A A1; A1.m_nTest = 1;
A A2; A2.m_nTest = 2;
Subject<EventType> s;
s.registerObserver(EventType::GREEN, bar);
s.registerObserver(EventType::GREEN, std::bind(&A::A_Bar, A2));
s.registerObserver(EventType::GREEN, std::bind(&A::A_Bar, A1));
s.notify(EventType::GREEN);
}
Since the first parameter on becomes the class from which it's called. I get exactly what I'd like:
But now I want to also have the notify pass some information to the observer class. Thus I have modified the code to the following:
template <typename Event>
class Subject
{...
void notify(const Event& event, int nParameter) const
{
for (const auto& obs : observers_.at(event)) obs(nParameter);
}
private:
std::map<Event, std::vector<std::function<void(int)>>> observers_;
};
And now my I'd like to register:
s.registerObserver(EventType::GREEN, std::bind(&A::A_Foo, A2));
Can anyone help me out what I'm missing or how to do this. I don't really want to make my Subject class know about the Observer class by adding it into the function interface. Thanks
Your code using bind
may be problematic since it copies the objects A2 and A1, you can use &A2 and &A2 if you want to reference the original objects. To answer your question, you can use:
s.registerObserver(EventType::GREEN, std::bind(&A::A_Foo, &A2, std::placeholders::_1));
Or use lambda, which I'd recommend:
s.registerObserver(EventType::GREEN, [&](int i){ A2.A_Foo(i); });