I have the following two classes that exhibit the Command pattern. (Unfortunately, both have a unique method name.)
//pseudocode
class Subscriber {
virtual void receive(const Event&) = 0;
}
class Dispatcher {
virtual void dispatch(const Event&) = 0;
}
I have a class template that has a list of some type with a method to iterate over this list.
//pseudocode
template<typename T>
class Registry {
typedef list<T> ObjectList;
ObjectList _objects;
void iterate(const Event& event) {
for_each(_objects.begin(), _objects.end(), ...); //not sure what to do here
}
}
I would like to use mem_fun to create a Functor that calls receive or dispatch as appropriate. I'm able to create a simple use case where I simply invoke a method without any params. I.e.
//pseudocode
class Simple {
void simple() {/*...*/}
}
and then I iterate:
for_each(_objects.begin(), _objects.end(), mem_fun(&Simple::simple);
Unfortunately, I have no idea how to get the event param passed to mem_fun. Looking at the headers, it does appear that I can pass a single param, but I'm not well versed in C++ to understand what I need to do.
Ultimately, I would like to make the iterate method accept a type of functor so it will fire that method on every method in the list.
I would prefer to avoid Boost...I think this is entirely possible without dragging this framework into the mix.
Thanks!
This may be the most straight-forward way:
class event_forwarder // make private in Registry
{
public:
event_forwarder(const Event& event) :
mEvent(event)
{}
void operator()(Subscriber& subcriber) const
{
subscriber.receive(mEvent);
}
void operator()(Dispatcher& dispatcher) const
{
dispatcher.dispatch(mEvent);
}
private:
const Event& mEvent;
};
Then:
for_each(_objects.begin(), _objects.end(), event_forwarder(event));
If I understand correctly, what you want is std::bind2nd:
std::for_each(_objects.begin(), _objects.end(),
std::bind2nd(std::mem_fun_ref(&Subscriber::receive), event));
The member-function Subscriber::receive has two parameters. The first is the implicit this pointer, and the second the const Event &. std::bind2nd, given a function f taking two arguments, returns a function f_1 taking one argument, that invokes the original function f with a fixed value for the second argument.
Edit:
To handle the different names of the dispatch functions, you can make the dispatch function a template parameter:
//pseudocode
template<typename T, void (T::*dispatch_method)(Event)>
class Registry {
typedef list<T> ObjectList;
ObjectList _objects;
void iterate(const Event& event) {
std::for_each(_objects.begin(), _objects.end(),
std::bind2nd(std::mem_fun_ref(dispatch_method), event));
}
}
Unfortunately, there does not seem to be a way to make bind2nd handle const reference parameters, so my whole solution is moot, unless copying Event objects is fine with you. This will work in C++0x with std::bind though, and the idea of making the dispatch function a template parameter is still valid. You can even use traits, to make that mechanism even more flexible.
You could create a functor class that wraps your Subscriber and Dispatcher classes, e.g.
class MyFunctor {
public:
virtual void Execute(const Event& event) = 0;
};
class MySubscriberFunctor : public MyFunctor {
private:
Subscriber subscriber_;
public:
void Execute(const Event& event) {
subscriber_.receive(event);
}
};
class MyDispatcherFunctor : public MyFunctor {
private:
Dispatcher dispatcher_;
public:
void Execute(const Event& event) {
dispatcher_.dispatch(event);
}
};
Your object list could then store these functor wrappers as a list of MyFunctor instances. This way you can call Execute() on them and let them delegate to the underlying classes. You should really have an operator() instead of Execute() to get a "real" functor, but you get the idea.
Cheers
Check if you have tr1. If you have tr1, it contains std::bind, which is almost exactly equivalent to the boost implementation. This should be found in the <functional> header.
If you don't have tr1, consider using Boost. I would strongly suggest using at least boost::bind, as it's lightweight and header only.
If you don't have tr1 and won't use Boost, you want to mix bind2nd and mem_fun1. The first binds the second parameter (in this case, your event; the object will be the first) and mem_fun1 is the same as mem_fun, but it expects two arguments, the object to be called on and one parameter to pass the member function being called. This is a complete mess, though.
If you do have access to bind, it's fairly easy.
for_each(objects.begin(), objects.end(), bind(&Simple::simple, _1, event))
Related
Say I have a templated class that wraps its template argument to provide some extra functionality, like the ability to persist the object's state to disk:
template<typename T>
class Persistent {
std::unique_ptr<T> wrapped_obj;
public:
Persistent(std::unique_ptr<T> obj_to_wrap);
void take_snapshot(int version);
void save(int to_version);
void load(int to_version);
}
I want to have another class, let's call it PersistentManager, store a list of these templated Persistent objects and call their member methods without knowing their template parameters. There are two ways I can see to do that: use std::function to erase the template type from each method, or use an abstract base class and virtual function calls.
Using std::function, each Persistent object would be capable of returning a bundle of std::functions bound to its members:
struct PersistentAPI {
std::function<void(int)> take_snapshot;
std::function<void(int)> save;
std::function<void(int)> load;
}
template<typename T>
PersistentAPI Persistent<T>::make_api() {
using namespace std::placeholders;
return {std::bind(&Persistent<T>::take_snapshot, this, _1),
std::bind(&Persistent<T>::save, this, _1),
std::bind(&Persistent<T>::load, this, _1)}
}
Then the PersistentManager can store a list of PersistentAPIs, and have a method like this:
void PersistentManager::save_all(int version) {
for(PersistentAPI& bundle : persistents) {
bundle.save(version);
}
}
Using inheritance, I would create an abstract class with no template parameters that defines each of Persistent's methods as virtual, and make Persistent inherit from it. Then the PersistentManager can store pointers to this base class, and call the Persistent methods through virtual function calls:
class AbstractPersistent {
public:
virtual void take_snapshot(int version) = 0;
virtual void save(int to_version) = 0;
virtual void load(int to_version) = 0;
}
template<typename T>
class Persistent : public AbstractPersistent {
...
}
void PersistentManager::save_all(int version) {
for(AbstractPersistent* obj : persistents) {
obj->save(version);
}
}
Both of these approaches add some overhead to the function call from PersistentManager: rather than dispatching the function call directly to a Persistent instance, they require going through an intermediary layer, either the std::function object or the virtual function table in AbstractPersistent.
My question is, which approach adds less overhead? Since these are both fairly opaque parts of the standard library, I don't have a good sense of how "expensive" a std::function call is compared to a virtual function call through a base class pointer.
(I've found a few other questions on this site asking about the overhead of std::function, but they all lack a specific alternative to compare against.)
I was hesitating a bit to answer this question, since it could easily boil down to opinions. I have been using std::function in a project, so I might just as well share my two cents (and you can decide what to do with the input).
Firstly, I would like to iterate what's already been said in the comments. If you actually want to see the performance, you have to do some benchmarking. Only after benchmarking, you can derive your conclusions.
Luckily, you can use quick-bench for quick benchmarking(!). I fed the benchmark with your two versions, adding a state that is increased for each call, and a getter for the variable:
// Type erasure:
struct PersistentAPI {
std::function<void(int)> take_snapshot;
std::function<void(int)> save;
std::function<void(int)> load;
std::function<int()> get;
};
// Virtual base class
class AbstractPersistent {
public:
virtual void take_snapshot(int version) = 0;
virtual void save(int to_version) = 0;
virtual void load(int to_version) = 0;
virtual int get() = 0;
};
Each function simply increases an integer in the corresponding class, and returns it with get() (hoping that the compiler does not remove all unnecessary code).
The result is in favor of virtual functions, and for both Clang and GCC, we have around 1.7 speed difference (https://quick-bench.com/q/wUbPp8OdtzLZv8H1VylyuDnd2pU, you can change compiler and recheck).
Now to the analysis: why is the abstract class seemingly quicker? Well, there are more indirections with std::function, but also there's another indirection in the wrapping before, when we call std::bind(!). Listening to Scott Meyers, lambdas are to prefer over std::bind, not only for their ease of syntax for people (std::placeholders is no beauty), but their of syntax for the compiler! A lambda call is easier to inline.
Inlining is very important for performance. If a explicit call can be avoided by added the code where we call, we can save some cycles!
Changing std::bind to lambdas, and performing again, we have very similar performance between std::function and inheritance (for both Clang and GCC): https://quick-bench.com/q/HypCbzz5UMo1aHtRpRbrc9B8v44.
So, why are they similar? For Clang and GCC, std::function is internally using inheritance. Type erasure, as it is implemented here, is simply hiding the polymorphism.
(Note that this benchmark might be misleading, since the call for both cases could be completely inlined, thus no indirection is used at all. The test case might have to be a bit more tricky to trick the compiler.)
So let's say you have either Clang and GCC as compilers, which method should you use?
The PersistentAPI is more flexible, since actually take_snapshot, save and load are basically function pointers, and do not need to be assigned to a single class! With
struct PersistentAPI {
std::function<void(int)> take_snapshot;
std::function<void(int)> save;
std::function<void(int)> load;
};
, it is fully reasonable as a developer to believe that PersistentAPI is meant to dispatch to multiple objects, and not just a * single one*. take_snapshot could for example dispatch to a free function, whereas save and load to two different classes. Is this the flexibility you want? Then that's what you should use. Generally, I would use std::function through the API to let the user register a callback to any callable of choice.
If you want to use type erasure, but want to hide the inheritance for some reason, you could build your own version. std::function accepts all types having operator(), we can build one that accepts all classes having the interface "take_snapshot, save and load". It's good to practice!
// probably there is a better name for this class
class PersistentTypeErased {
public:
template<typename T>
PersistentTypeErased(T t) : t_(std::make_unique<Model<T>>(t)) {}
void take_snapshot(int version) { t_->take_snapshot(version); }
void save(int to_version) { t_->save(to_version); }
void load(int to_version) { t_->load(to_version); }
private:
struct Concept
{
virtual void take_snapshot(int version) = 0;
virtual void save(int to_version) = 0;
virtual void load(int to_version) = 0;
};
template<typename T>
struct Model : Concept
{
Model(T t) : t_(t) {}
void take_snapshot(int version) { t_.take_snapshot(version); }
void save(int to_version) { t_.save(to_version); }
void load(int to_version) { t_.load(to_version); }
T t_;
};
std::unique_ptr<Concept> t_;
};
The technique is similar to std::function, and now you probably also can see how type erasure uses polymorphism under the hood. You can see how it is used here.
I will describe my problem the simplest as I can.
What is my issue:
I have frist class as a singleton:
class CTimer1
{
public:
static CTimer1 * getInstance(); //This gives me pointer to instance
void setChannelA(uint8_t compareValue);
private:
//Cnstructors
CTimer1(); //Prevent consttuction but allow in getInstance
CTimer1(const CTimer1&); //Prevent construction by copying
CTimer1& operator=(const CTimer1&); //Prevent assigment
~CTimer1(); //Prevent unwanted destruction
static CTimer1 * timerInstance;
static bool isCreated;
};
And here is second class where I would like to have possibility to call setChannelA method from CTimer1 class as a setPwm method from CServo class:
class CServo {
public:
CServo();
~CServo();
public:
//public methods
void registerPwmTimer(void (*callback)(uint8_t u8_buffer));
void (*setPwm)(uint8_t u8_buffer); //As this method I would like to call setChannelA from CTimer1 class
};
Here is registerPwmTimer method:
void CServo::registerPwmTimer(void (*callback)(uint8_t u8_buffer))
{
setPwm = callback;
}
Then I have tried to assign pointer to this method as a following:
int main()
{
CTimer1 * timer1 = CTimer1::getInstance();
CServo servo1();
servo1.registerPwmTimer(timer1->setChannelA);
servo1.setPwm(10); //This is example how I want to call setChannelA method
while(1)
{
}
}
I have error:
error: no matching function for call to 'CServo::registerPwmTimer(<unresolved overloaded function type>)'
What is important:
I can't use std::function because this is some part of code in C++ for embedded device, so I need to save memory consumption. Is there any way that I will be able to achieve this effect? If ony one possibility to do this is ot use some std library please for answers too. Thanks for your help.
Your problem is that a function pointer necessarily has to point to a static function. When you invoke an instance function (a method) there is a hidden first argument, which is the object on which the function was invoked. (This hidden argument is available as this within the function's definition.)
Your CServo::registerPwmTimer() function signature is simply incompatible with invocation of a member function; function pointers alone do not provide a way to bind an argument to the pointer, so even if you could convey the member function pointer using a (free) function pointer type, the hidden this argument could not be determined when the function pointer was invoked.
To put it another way, it would fail for the same reason that trying CTimer1::setChannelA(0) would fail -- you want to invoke that method, but you haven't communicated which object on which to invoke it.
Change the signature of CServo::registerPwmTimer to accept an std::function object instead of a raw function pointer. std::function objects can be constructed from function pointers, but they can also be constructed from lambdas, and some standard library functions return function objects:
void registerPwmTimer(std::function<void(uint8_t)>);
Now, you can use std::bind to create a new function that binds the object instance to the member function pointer:
servo1.registerPwmTimer(std::bind(&CTimer1::setChannelA, timer1));
Note that std::bind does not extend the lifetime of the object pointed to by timer1. If the returned function is invoked after that object is destructed, the result is undefined behavior.
Another alternative would be to accept both an instance and a pointer to a member function. The problem with this approach is it requires using templates:
template <typename T>
void registerPwmTimer(void (T::*)(uint8_t), T&);
This isn't bad in itself, but what you'll wind up doing is creating a polymorphic wrapper class so that you can insert this into your callback list alongside other callbacks that don't share the same T. At that point, you're just recreating std::function, since std::function already serves the purpose of being a polymorphic wrapper around callable things.
To illustrate the mess of implementing a polymorphic callable wrapper yourself, here is a very light example. I will show the declarations of a set of these types, and link to an example implementation.
This is the base type, with a pure virtual operator() that serves as the invocation operation.
class poly_callable
{
public:
virtual void operator()(int) const = 0;
};
Now we have a type for function pointers (also works with pointer-to-functor):
template <typename T>
class fn_poly_callable : public poly_callable
{
public:
typedef T fn_type;
fn_poly_callable(T);
virtual void operator()(int) const;
private:
T fn;
};
And one for member functions -- oh, but const member functions and non-const member functions are not interchangeable, so we need an extra template parameter for that:
template <typename T, typename M = void (T::*)(int)>
class member_poly_callable : public poly_callable
{
public:
typedef T object_type;
typedef M member_fn_type;
member_poly_callable(member_fn_type, object_type&);
virtual void operator()(int) const;
private:
member_fn_type mfn;
object_type& target;
};
Plus we'll want some helper functions to allow the compiler to infer the template types. One for function pointers:
template <typename T>
std::unique_ptr<poly_callable> make_poly_callable(T fn)
{
return std::unique_ptr<poly_callable>(new fn_poly_callable<T>(fn));
}
Two for member functions (const and non-const):
template <typename T>
std::unique_ptr<poly_callable> make_poly_callable(void (T::*mfn)(int), T& target)
{
return std::unique_ptr<poly_callable>(new member_poly_callable<T>(mfn, target));
}
template <typename T>
std::unique_ptr<poly_callable> make_poly_callable(void (T::*mfn)(int) const, T& target)
{
return std::unique_ptr<poly_callable>(new member_poly_callable<T, void (T::*)(int) const>(mfn, target));
}
If you want to see it all in action, I made a "simple" and working example.
So... just use std::function. There's no reason to reinvent this stuff.
I'm new to C++ and I don't want to use any libraries because I want to really understand whats going on internally.
Additionally I try to keep my library-use as low as possible (to improve performance and) to make it as platform-independent as possible (without exporting the library).
So all in all I'd like to not use std or boost to solve this problem.
My question:
I have an EventHandler which has a function:
template<class T> void EventHandler::SetCallbackFunction(T* obj, void (T::*mem_fkt)(void));
I have to save the object and the function to call it later.
There are 2 possibilities:
EventHandler as template class (and typedef)
void* -> but to call the function I need to cast it back and for that I need the classname :/
Why these dont work:
- The EventHandler can't be a template class because it needs to handle multiple classes..
- void* -> I don't know how to save the classname to cast it later on
How can I do that?
(Or is there another way? Maybe a way to save the classname to cast it later on?)
EDIT:
Furthermore I may need to register multiple callback functions per class so an Interface is not really an option.
class A {
public:
void CallbackFktForEventHandler();
void CallbackFktForAnimationHandler();
etc...
};
And I know that you could solve it based on something like this:
class A{
public:
void Callback();
static void CallbackStatic(void* self){
static_cast<A*>->CallBack();
};
};
But this restricts me too much for my taste.
You could try this:
Create a (pure virtual) base-class that only has one function call():
class Function{
virtual void call()=0;
}
Create a templated class which stores a function-pointer and an object and make it inherit from Function
template<typename T>
class TemplatedFunction{
void (T::*m_fkt)(void);
T* m_obj;
TemplatedFunction(T* obj, void (T::*fkt)(void)):m_fkt(fkt),m_obj(obj){}
void call{
(m_obj->*m_fkt)();
}
}
And then store pointers to Function in your Event-Handler and just use Function->call()
Try it online: http://ideone.com/3Hu5pw
But you will make your life a lot easier if you use at least the standard library. Basically i would use std::bind to bind your object and your member-function together to a function void()(void) and then store these objects inside a std::vector.
Edit: Oktalist was faster ;)
You can use type erasure. You effective save the type of obj by instantiating a class template which implements a non-template virtual interface. This is essentially how std::function is implemented, so you're just writing your own basic version of std::function.
struct ICallback
{
virtual void call() = 0;
};
template <class T>
struct Callback : public ICallback
{
virtual void call() override { (m_obj->*m_func)(); }
Callback(T *obj, void (T::*func)()) : m_obj(obj), m_func(func) {}
T *m_obj;
void (T::*m_func)();
};
template <class T>
std::unique_ptr<ICallback> wrap(T *obj, void (T::*func)())
{
return std::make_unique<Callback<T>>(obj, func);
}
If you don't want to use std::unique_ptr you can roll your own or use an evil raw owning pointer.
I am working on an event daemon in C++ that I would like to use member function callbacks. Basically an event queue would collect events which the daemon continuously services. There is a base class Event struct with an ID and all events would derive from it. I would like the methods registered for each event to use the derived event type in their signature.
struct Event
{
unsigned int eventId;
};
struct EventA : public Event
{
unsigned int x;
unsigned int y;
};
// and struct EventB, EventC (use your imagination...)
const unsigned int EVENT_A = 1;
const unsigned int EVENT_B = 2;
const unsigned int EVENT_C = 3;
class Foo
{
public:
void handlerMethod_A(const EventA& e);
void handlerMethod_B(const EventB& e);
};
class Bar
{
public:
void handlerMethod_C(const EventC& e);
};
Then the Daemon would allow these classes to subscribe their member functions using their 'this' pointer.
class EventDaemon
{
public:
void serviceEvents();
template <class CallbackClass, class EventType>
void subscribe(
const unsigned int eventId,
CallbackClass* classInstancePtr,
void (CallbackClass::*funcPtr)(EventType));
private:
Queue<Event*> eventQueue_;
};
So outside this class you could do something like:
EventDaemon* ed = new EventDaemon();
Foo* foo = new Foo();
Bar* bar = new Bar();
ed->subscribe(EVENT_A, foo, Foo::handlerMethod_A);
ed->subscribe(EVENT_B, foo, Foo::handlerMethod_B);
ed->subscribe(EVENT_C, bar, Bar::handlerMethod_C);
And the EventDaemon loop would be along the lines of
void EventDaemon::serviceEvents()
{
while (true)
{
if (eventQueue_.empty())
{
// yield to other threads
}
else
{
// pop an event out of the FIFO queue
Event e* = eventQueue_.pop();
// somehow look up the callback info and use it
classInstancePtr->*funcPtr(reinterpret_cast<?*>(e));
}
}
}
So my question is how I can store the 'this' pointers and member function pointers in some sort of array by event ID. That way I could look up the 'classInstancePtr' and 'funcPtr' by using e->eventId and the event type as well for the reinterpret cast.
You are working too hard. Use boost functions:
http://www.boost.org/doc/libs/1_47_0/doc/html/function.html
These work whether you have a object or not. They will increase your compile time.
Note, whenever you come across these types of questions where you know many people must have had the same problem, there is probably a simple option and, if it is not in the standard library, it is probably in boost.
In response to Nick, I'm constantly throwing boost function objects into vectors and whatnot.
I've found that, while boost function objects can hold object references, having them do so can lead to bugs with object lifetimes and it is better to have them hold copies of the class objects (you run into the same bugs however you try to hold a reference to a object instance that you don't necessarily control the lifetime of). The pattern:
class Foo
{
struct Member
{
// member variable definitions
};
shared_ptr<Member> m_; // the only real member variable
public:
// etc. including the all-important copy
// constructor and assignment operator and
// don't forget the member function that gets stuck into
// the boost function as a callback!
};
where all the member variables get held in a shared_ptr allows for good performance and you don't have to worry about lifetimes of objects held by function objects because you can copy them by value. Threaded code (what I always seem to be writing nowadays) needs additional things like at least one boost mutex element in Member or some other way to assure values don't get stomped on.
boost::function [or, if your system supports it, std::function] will take care of holding the this pointer quite well, with the added benefit of not requiring an actual object if it isn't necessary. So instead of void (SomeType::*)(EventA) you have std::function<void(EventA)>, and you call std::bind as appropriate.
subscribe(EVENT_A, std::bind(&foo::handleEventA, &foo, std::placeholders::_1));
A trivial wrapper function can be used to provide the same signature as you originally proposed and hide the nasty placeholders.
You do, of course, still have the issue of each event type having its own signature, and the need to ensure you use the correct Event ID code. In both cases, your base Event type can help out. Your callback need not accept an EventA&; it can accept an Event&, and dynamic_cast it to an EventA at runtime. For the ID, query the type directly.
struct Event {
virtual void ~Event() { }
virtual int ID() =0;
};
template<typename E>
struct EventHelper : Event {
virtual int ID() { return E::EventID; }
};
struct EventA : EventHelper<EventA> {
static const int EventID = 89;
};
Now, if you have an Event* object [when you go to dispatch your events], you can do p->ID() to get the appropriate ID, and if you have a EventA type [when you register your callbacks] you can do EventA::EventID.
So now, all you have to store is a std::function<void(const Event&)> and an associated int value for each of your callbacks, no matter what the actual type of event you have.
void subscribe(int id, std::function<void(const Event&)> f) {
callbacks.insert(std::make_pair(id, f));
}
template<typename E>
void subscribe(std::function<void(const Event&)> f) {
subscribe(E::EventID, f);
}
template<typename O, typename E>
void subscribe(O* p, void (O::*f)(const Event&)) {
subscribe<E>(std::bind(f, p, std::placeholders::_1));
}
You still have the issue that user error when subscribing can result in a function being called incorrectly. If you've used dynamic_cast correctly within the callback, this will get caught at runtime, but a compile time check would be nice. So what if we automate that dynamic_cast? For this step, I'm going to use c++11 lambdas, but it can be implemented in C++03 as well using a variety of methods.
template <class CallbackClass, class EventType>
void subscribe(CallbackClass* classInstancePtr, void (CallbackClass::*funcPtr)(EventType)) {
subscribe<EventType::EventID>([&](const Event& e) {
(classInstancePtr->*funcPtr)(dynamic_cast<const EventType&>(e));
});
}
So now we've gone full circle back to your original interface where your callbacks accept the actual type they are going to be working on, but internally you've squeezed them all into a common signature.
Okay, so I finished an implementation of my original desired interface. I was looking through Dennis' answer but eventually got lead to functors and I realized what I was looking for was a simple polymorphic solution. I failed to grasp before that I could create a non-templated base class with which to use for storing templated classes in vectors/arrays. I think this is what mheyman was trying to tell me... so I apologize I didn't get it right away. Just to clarify though I was really looking for the implementation solution for my own benefit and knowledge, not just a 3rd party library to get the job done. So I guess I would be looking for how Boost functions work, not just that they exist and are awesome.
If anyone is still interested here are the important parts of what I ended up with (minus some extraneous stuff and error checking):
EventFunctor is basically a pointer to member function template class
EventFunctorBase is the non-templated base class used to store them in a vector
The Event is dynamic cast using the templated type before being used to invoke the callback
class EventDaemon
{
public:
template <class CallbackClass, class EventType>
void subscribe(
const EventId eventId,
CallbackClass* callbackClassInstancePtr,
void (CallbackClass::*funcPtr)(const EventType&));
private:
EventFunctorBase* callbacks_[MAX_NUM_EVENTS];
};
template <class CallbackClass, class EventType>
void EventDaemon::subscribe(
const EventId eventId,
CallbackClass* callbackClassInstancePtr,
void (CallbackClass::*funcPtr)(const EventType&))
{
callbacks_[eventId] = new EventFunctor<CallbackClass,EventType>(callbackClassInstancePtr,funcPtr);
}
class EventFunctorBase
{
public:
EventFunctorBase();
virtual ~EventFunctorBase();
virtual void operator()(const Event& e)=0;
};
template <class CallbackClass, class EventType>
class EventFunctor : public EventFunctorBase
{
public:
EventFunctor(
CallbackClass* callbackClassInstancePtr,
void (CallbackClass::*funcPtr)(const EventType&));
virtual void operator()(const Event& e);
private:
CallbackClass* callbackClassInstancePtr_;
void (CallbackClass::*funcPtr_)(const EventType&);
};
template <class CallbackClass, class EventType>
EventFunctor<CallbackClass,EventType>::EventFunctor(
CallbackClass* callbackClassInstancePtr,
void (CallbackClass::*funcPtr)(const EventType&))
:
callbackClassInstancePtr_(callbackClassInstancePtr),
funcPtr_(funcPtr)
{
}
template <class CallbackClass, class EventType>
/*virtual*/ void EventFunctor<CallbackClass,EventType>::operator()(const Event& e)
{
(callbackClassInstancePtr_->*funcPtr_)(dynamic_cast<const EventType&>(e));
}
EventDaemon loop
while (true_)
{
if (eventQueue_->empty())
{
// yield to other threads
}
else
{
Event* e = eventQueue_.pop();
(*(callbacks_[e->ID]))(*e);
}
}
My final steps here will be to try and remove the need to have the developer define an ID for each event... of course this might end up a new post later this week.
Forgive my ignorance in asking this basic question but I've become so used to using Python where this sort of thing is trivial that I've completely forgotten how I would attempt this in C++.
I want to be able to pass a callback to a function that performs a slow process in the background, and have it called later when the process is complete. This callback could be a free function, a static function, or a member function. I'd also like to be able to inject some arbitrary arguments in there for context. (ie. Implementing a very poor man's coroutine, in a way.) On top of that, this function will always take a std::string, which is the output of the process. I don't mind if the position of this argument in the final callback parameter list is fixed.
I get the feeling that the answer will involve boost::bind and boost::function but I can't work out the precise invocations that would be necessary in order to create arbitrary callables (while currying them to just take a single string), store them in the background process, and invoke the callable correctly with the string parameter.
The callback should be stored as a boost::function<void, std::string>. Then you can use boost::bind to "convert" any other function signature to such an object, by binding the other parameters.
Example
I've not tried to compile this, but it should show the general idea anyways
void DoLongOperation(boost::function<void, const std::string&> callback)
{
std::string result = DoSomeLengthyStuff();
callback(result);
}
void CompleteRoutine1(const std::string&);
void CompleteRoutine2(int param, const std::string&);
// Calling examples
DoLongOperation(&CompleteRoutine1); // Matches directly
DoLongOperation(boost::bind(&CompleteRoutine2, 7, _1)); // int parameter is bound to constant.
// This one is thanks to David RodrÃguez comment below, but reformatted here:
struct S
{
void f( std::string const & );
};
int main()
{
S s;
DoLongOperation( boost::bind( &S::f, &s, _1 ) );
}
Sounds like you want to use the Observer pattern.
The easiest way:
class Callback
{
public:
virtual ~Callback() {}
virtual Callback* clone() const = 0;
// Better to wrap the call (logging, try/catch, etc)
void execute(const std::string& result) { this->executeImpl(result); }
protected:
// Don't make sense to have them public
Callback() {}
Callback(const Callback&) {}
Callback& operator=(const Callback&) { return *this; }
private:
virtual void executeImpl(const std::string& result) = 0;
};
// Example
class Example: public Callback
{
public:
Example(int a, int b): Callback(), mA(a), mB(b) {}
virtual Example* clone() const { return new Example(*this); }
private:
virtual void executeImpl(const std::string& result) {}
int mA;
int mB;
};
And then, you can pass the callback class (by pointer / reference) to the process. The class has a state, as required, and may be copied if necessary (if not, drop the clone).