Creating multicast events with std::tr1::function (or boost::function) - c++

I'm attempting to create C#-like multicast delegates and events using features from TR1. Or Boost, since boost::function is (mostly) the same as std::tr1::function. As a proof of concept I tried this:
template<typename T1>
class Event
{
private:
typedef std::tr1::function<void (T1)> action;
std::list<action> callbacks;
public:
inline void operator += (action func)
{
callbacks.push_back(func);
}
inline void operator -= (action func)
{
callbacks.remove(func);
}
void operator ()(T1 arg1)
{
for(std::list<action>::iterator iter = callbacks.begin();
iter != callbacks.end(); iter++)
{
(*iter)(arg1);
}
}
};
Which works, sort of. The line callbacks.remove(func) does not. When I compile it, I get the following error:
error C2451: conditional expression of type 'void' is illegal
Which is caused by line 1194 of the list header, which is in the remove function. What is causing this?

If you're you're looking for multicast delegates in C++, your best bet would be Boost.Signals2. You can also use Boost.Bind to make it possible to use member functions for callbacks.
You can look at my example here for simple usage of Boost.Signals and Boost.Bind.
Boost.Signal provides lifetime management facilities to ensure that events are not published to subscribers that no longer exist.

I think this is exactly same problem: comparing-stdtr1function-objects
(basically you can't compare functors, that's why erase or anything using operator== won't work)

You should look into Sutter's Generalizing Observer

Related

Function Pointers as Event Callbacks in a st

I am currently trying to implement an event system where layers can subscribe to certain event types. I am struggling with function pointers for the callback methods. In the layer.h file I have the OnEvent function and a function pointer which looks like this:
void OnEvent(const Event& e);
void(Engine::Layer::*m_EventCallback)(const Event& e);
In the constructor of a layer I simply do this:
m_EventCallback = OnEvent;
To keep track of which layer subscribed to which EventType I have defined a struct as folling:
struct CallbackData {
EventType type;
void(Engine::Layer::*OnEvent)(const Event& e);
int layerID;
bool isActive;
};
I have an EventDispatcher and its dispatch function looks something like this:
bool EventDispatcher::Dispatch(const Event& e)
{
for (CallbackData& calldata : m_Callbacks) {
if (calldata.type == e.GetEventType() && calldata.isActive) {
calldata.OnEvent(e);
}
}
//TODO work on this so it only returns true if the event has been properly dispatched
return true;
}
There is also a subscribe function which creates an instance of CallbackData and pushes it into a vector which looks like this:
void EventDispatcher::Subscribe(EventType type, void(Engine::Layer::*OnEvent)
(const Event& e), int layerID)
{
CallbackData temp = { type, OnEvent, layerID, true };
m_CallbackInsert = m_Callbacks.emplace(m_CallbackInsert, temp);
}
So if the type is of callback data is the same as the event references type the OnEvent function should get called via the function pointer.
The function pointer defintion needs to have Engine:: which is just a namespace and Layer which is the class where the OnEvent lies. I dont know why it needs the namespace because everything I do here is defined in the namespace.
But the main question is how do I properly define the function pointer and then call it the way showcased here?
The exact error message is this:
expression preceding parentheses of apparent call must have(pointer-to-)function type
Please dont link sites with already implemented event systems. I have already looked at those and didnt really understand much. Thats why I want to do it myself so I do understand it.
Thanks in advance!
Assuming I understand what you're doing...
You have an EventDispatcher, and he needs to keep a registry of possible callbacks to make. I'm going to cut & paste a little code I use then explain it.
First, this is the relevant portion of my Route object.
class Route {
public:
typedef std::function<void(const HTTPServerRequest &, HTTPServerResponse &)> Callback;
Callback callback;
};
class Router {
public:
void addRoute(const std::string &method, const std::string &path, Route::Callback callback);
};
That part works about how you would expect and doesn't require anything special. This creates an array of Route objects, with the callback method being given the callback passed into addRoute(). When I want to dispatch on this particular route:
route->callback(request, response);
You probably know that part, too.
For my code, I'm making method calls into an object. To pass that, you have two choices. The first is to use std::bind() -- which I really dislike.
So I use lambdas.
addRoute("GET", "/ping", [=](const HTTPServerRequest &request, HTTPServerResponse &response) { ping(request, response); } );
Is this absolutely the most efficient? I have no idea. But performance isn't ultra-sucky, so this is what I do.
Basically, I keep std::function<> pointers, and those are really easy to use. You can pass a lambda as a std::function<> as long as the signature matches.
The other choice is to use std::bind -- which, as I said, I don't like, mostly because I think it's uglier than using a lambda. But that's definitely an opinion, not a fact. Using std::bind may be a better way, but I don't have any code to show you doing it that way.
I'm not entirely sure this actually solves the confusion you're having, but if it's close, just comment, and I'll try to clarify.

Using parameter packs to automate dynamic_cast checks

I'm trying to implement a communication system inside of a GUI. I would like to avoid the visitor pattern for maintainability reasons. Likewise making a dynamic_cast if else statement is not maintainable. The closest I've come is implementing multiple dispatch with tables from Scott Meyers' More Effective C++.
So far I have:
SubmitCommand(BaseCommand* pCommand)
{
m_Distpatcher->Dispatch<DerivedCommand1>(pCommand);
m_Distpatcher->Dispatch<DerivedCommand2>(pCommand);
m_Distpatcher->Dispatch<DerivedCommand3>(pCommand);
}
Where I would like to be is:
SubmitCommand(BaseCommand* pCommand)
{
m_Distpatcher->Dispatch<DerivedCommand1,
DerivedCommand2,
DerivedCommand3>(pCommand);
}
Where dispatch is a automated way of checking dynamic_cast results for incoming commands.
template<typename K>
void Dispatch(ICommand* pCommand)
{
auto pConcreteCommand = dynamic_cast<K*>(pCommand);
if (pConcreteCommand)
{
//call Recieve on the interface of the owner class
m_pInstance->Recieve(pConcreteCommand);
}
}
In this case the specific module would be checked at compile time to make sure it has a function for each argument in the template. Is code block 2 possible?
You might do something like:
template <typename ... Ts>
void Distpatcher::Dispatch(BaseCommand* pCommand)
{
(DispatchUnique<Ts>(pCommand), ...); // C++17
}
so
m_Distpatcher->Dispatch<DerivedCommand1,
DerivedCommand2,
DerivedCommand3>(pCommand);
would be equivalent to
m_Distpatcher->DispatchUnique<DerivedCommand1>(pCommand);
m_Distpatcher->DispatchUnique<DerivedCommand2>(pCommand);
m_Distpatcher->DispatchUnique<DerivedCommand3>(pCommand);

Simple module system (callbacks)

I'm trying to make a simple module engine, but I don't really know where to start, I want to create something like this:
int awesomefunction() {
// do something here
execute_awesomefunction_callbacks_here();
// some more stuff
}
The *execute_awesomefunction_callbacks_here();* would execute all the functions that are in a std::vector
Any ideas on how to achieve this? Or are there any better ways of doing this?
You could implement it with an std::vector of std::function. The only constraint is that all the function objects must have compatible return type and argument types.
class Publisher {
public:
void registerSubscriber(std::function<int(int, double)> callback) {
callbacks_.push_back(callback);
int executeAwesomeFunction() const {
// loop over vector calling each function object.
}
private:
std::vector<std::function<double(int,double)>> callbacks_;
}
This requires C++11 support, but you can achieve the same using boost::function

Messaging system: Callbacks can be anything

I'm trying to write an event system for my game. The callbacks that my event manager will store can be both plain functions as well as functors. I also need to be able to compare functions/functors so I know which one I need to disconnect from the event manager.
• Initially I tried using boost::function; it handles functions and functors perfectly well, except it has no operator==, so I can't remove callbacks if I want to.
class EventManager
{
typedef boost::function<void (boost::weak_ptr<Event>)> Callback;
std::map<Event::Type, std::vector<Callback>> eventHandlerMap_;
};
• I also tried using boost::signal, but that also gives me a compilation problem related to operator==:
binary '==' : no operator found which takes a left-hand operand of type 'const Functor' (or there is no acceptable conversion)
void test(int c) {
std::cout << "test(" << c << ")";
}
struct Functor
{
void operator()(int g) {
std::cout << "Functor::operator(" << g << ")";
}
};
int main()
{
boost::signal<void (int)> sig;
Functor f;
sig.connect(test);
sig.connect(f);
sig(7);
sig.disconnect(f); // Error
}
Any other suggestions about how I might implement this? Or maybe how I can make either boost:: function or boost::signal work? (I'd rather use boost:: function though, since I've heard signal is rather slow for small collections of items.)
Edit: This is the interface of that I'd like EventManager to have.
class EventManager
{
public:
void addEventHandler(Event::Type evType, Callback func);
void removeEventHandler(Event::Type evType, Callback func);
void queueEvent(boost::shared_ptr<Event> ev);
void dispatchNextEvent();
};
You'll find that most generic function wrappers do not support function equality.
Why is this? Well, just look at your functor there:
struct Functor
{
void operator()(int g) {
std::cout << "Functor::operator(" << g << ")";
}
};
This Functor has no operator==, and therefore cannot be compared for equality. So when you pass it to boost::signal by value, a new instance is created; this will compare false for pointer-equality, and has no operator to test for value-equality.
Most functors don't, in fact, have value-equality predicates. It's not useful very much. The usual way to deal with this is to have a handle to the callback instead; boost::signals does this with its connection object. For example, take a look at this example from the documentation:
boost::signals::connection c = sig.connect(HelloWorld());
if (c.connected()) {
// c is still connected to the signal
sig(); // Prints "Hello, World!"
}
c.disconnect(); // Disconnect the HelloWorld object
assert(!c.connected()); c isn't connected any more
sig(); // Does nothing: there are no connected slots
With this, HelloWorld doesn't need to have an operator==, as you're referring directly to the signal registration.
Have you ever tried libsigc and libsigc++? I started using them in linux and fell in love with them. I now use them in my Windows applications as well. I believe it is more extensible and flexible than boost. It is also a breeze to implement.
I highly recommend you consider Don Clugston's "Member Function Pointers and the Fastest Possible C++ Delegates". You can find the article and download the code from here:
http://www.codeproject.com/KB/cpp/FastDelegate.aspx
Among many other benefits, his delegates provide comparison operators (==, !=, <) out of the box. I'm currently using them for a realtime system and find them excellent in every way. I do seem to recall we had to make a minor modification to fix a compiler portability issue; but, that experience will vary based on platform etc.
Also, the article is several years old so you may want to google around for updated code/discussion regarding this delegate implementation if you run into any problems.
No matter, I found the solution. A little template magic and things become simple(r):
template<typename F>
void EventManager::removeEventHandler(Event::Type evType, F func)
{
auto compare = [func](const Callback& other) -> bool {
F const* f = other.target<F>();
if (f == nullptr) return false;
return *f == func;
};
std::vector<Callback>& callbacks = ...;
auto pend = std::remove_if(callbacks.begin(), callbacks.end(), compare);
callbacks.erase(pend, callbacks.end());
}
template<typename R, typename F, typename L>
void EventManager::removeEventHandler(
Event::Type evType, const boost::_bi::bind_t<R, F, L>& func)
{
auto compare = [&func](const Callback& other) -> bool {
auto const* f = other.target<boost::_bi::bind_t<R, F, L>>();
if (f == nullptr) return false;
return func.compare(*f);
};
std::vector<Callback>& callbacks = ...;
auto pend = std::remove_if(callbacks.begin(), callbacks.end(), compare);
callbacks.erase(pend, callbacks.end());
}
I need to handle Boost.Bind objects separately because operator== doesn't actually do comparison for Bind objects, but produce a new functor that compares the result of the other two (read more). To compare Boost.Bind you have to use the member function compare().
The type boost::_bi::bind_t seems to be an internal type of Boost (I guess that's what the underscore in namespace '_bi' means), however it should be safe to use it as all overloads of boost::function_equal also use this type (reference).
This code will work for all types of functors as long as there is an operator== defined that does comparison, or if you're using Boost.Bind. I had a superficial look into std::bind (C++0x), but that doesn't seem to be comparable, so it won't work with the code I posted above.

Specify an inline callback function as an argument

Let me first explain what I'm trying to achieve using some pseudo-code (JavaScript).
// Declare our function that takes a callback as as an argument, and calls the callback with true.
B(func) { func(true); }
// Call the function
B(function(bool success) { /* code that uses success */ });
I hope this says it all. If not, please comment on my question so I can write a little more to clarify my issue.
What I want is to have code like this in C++.
I have tried to use lambda functions, but I was unable to specify a parameter type for those.
If your compiler is a fairly recent release (such as Visual Studio 2010 or GCC 4.5), you can use some new features from the new C++ standard, which is currently in ratification and should be published soon.
I don't know what you need to do to enable this in Visual Studio, but it should be well-documented either on MSDN or internal help.
For GCC 4.5, just add the -std=c++0x option to enable the new features.
One of these features is the Lambda syntax:
template <typename F>
void func_with_callback(F f) {
f(true);
}
int main() {
func_with_callback( [](bool t){ if(t) cout << "lambda called" << endl; } );
}
If you don't have access to a modern compiler, you can use techniques such as functors and libraries like boost::lambda, which can perform similarly.
EDIT: Upon reading your question again, it looks like you might be looking for anonymous functions in C++. If that's what you want, unfortunately the language does not support that feature. C++ requires you be a bit more verbose with those sorts of things at present time. If you need more than what boost::lamda is already providing you then you should probably separate it out as a normal function anyway.
In C and C++ this is accomplished using function pointers or functors and templates (C++ only).
For example (using the C++ way (functors))
//Define a functor. A functor is nothing but a class which overloads
//operator(). Inheriting from std::binary_function allows your functor
//to operate cleanly with STL algorithms.
struct MyFunctor : public std::binary_function<int, int, bool>
{
bool operator()(int a, int b) {
return a < b;
};
};
//Define a template which takes a functor type. Your functor should be
//should be passed by value into the target function, and a functor should
//not have internal state, making this copy cheap.
template <typename Func_T>
void MyFunctionUsingACallback(Func_T functor)
{
if (functor(a, b))
//Do something
else
//Do something else
}
//Example usage.
int main()
{
MyFunctionUsingACallback(MyFunctor());
}
Using the C way (function pointers):
//Create a typedef for a function pointer type taking a pair of ints and
//returning a boolean value.
typedef bool (*Functor_T)(int, int);
//An example callback function.
bool MyFunctor(int a, int b)
{
return a < b;
}
//Note that you use the typedef'd function here.
void MyFunctionUsingACallback(Functor_T functor)
{
if (functor(a, b))
//Do something
else
//Do something else
}
//Example usage.
int main()
{
MyFunctionUsingACallback(MyFunctor);
}
Note that you should prefer the C++ way because it will allow the compiler to
make more intelligent decisions with regards to inlining, unless for some reason
you are limited to the C subset.