Short version of my question:
When I tried to boost::bind io_service::post like this:
boost::bind(&boost::asio_io_service::post, &ios,
boost::bind(&MyClass::func, this, arg1, arg2));
I get errors like this:
error: no matching function for call to ‘bind(<unresolved overloaded function type>,
boost::asio::io_service*, boost::_bi::bind_t<void, boost::_mfi::mf2<void, MyClass,
const char*, const char*>, boost::_bi::list3<boost::_bi::value<MyClass*>,
boost::_bi::value<const char*>, boost::_bi::value<const char*> > >)’
How can I fix this?
Very simple test code: http://pastebin.com/V0uyLywC
Long version of my question:
I'm trying to write a generic event queue class, which you can add different types of events to the queue. You can subscribe to events by types, when that type of events is added, the subscribed callback function will be called.
An event queue object can potentially be subscribed by a different thread group from a different io_services. The internal queue of this class will be thread-safe using boost::lockfree:queue or boost::interprocess::message_queue (if this will be inter-process in the future). And the subscribed callback function will need to be called by its corresponding io_service's post, hence the attempted nested boost::bind above.
Is this a good and workable design?
Assuming this approach will work, I figured then an alternative would be also passing the io_service when you subscribe, but I was thinking 1) perhaps this class can be used when it does not involve io_services, and 2) this class shouldn't need to know about io_service.
Thanks all.
P.S. I have read boost::bind composition inside io_service::post function but it feels a bit different to my problem.
Update All solutions Live On Coliru
The problem
The first problem is that post has overloads, so you need to disambiguate. That's pretty ugly:
boost::bind(
static_cast<void (boost::asio::io_service::*)
(
boost::_bi::protected_bind_t<
boost::_bi::bind_t<
void,
boost::_mfi::mf2<void, MyClass, int, int>,
boost::_bi::list3<boost::_bi::value<MyClass *>,
boost::_bi::value<int>,
boost::_bi::value<int>
>
> > const&
)>(&boost::asio::io_service::post),
&ios_,
boost::protect(boost::bind(&MyClass::func, this, 7, 42)));
Of course, you could try to use decltype and some typedefs:
auto nested = boost::protect(boost::bind(&MyClass::func, this, 7, 42));
typedef decltype(nested) actual_t; // _bi::protected_bind_t<bind_t<void, mf2<void, MyClass, int, int>, list3<value<MyClass *>, value<int>, value<int> > > >
typedef void (boost::asio::io_service::*pmf)(actual_t const&);
boost::bind(static_cast<pmf>(&boost::asio::io_service::post), &ios_, nested);
But that would more or less refute the purpose of inline bind expressions in the first place.
Solution
Or you can use a helper functor, that hides the overload set behind a suitable polymorphic operator():
boost::bind(poster(ios_),
boost::protect(boost::bind(&MyClass::func, this, 7, 42)));
Where the poster helper looks like
struct poster {
typedef void result_type;
poster(boost::asio::io_service& ios) : ios_(ios) {}
boost::asio::io_service& ios_;
template<typename F> void operator()(F const& f) const {
ios_.post(f);
}
template<typename F> void operator()(F&& f) const {
ios_.post(std::move(f));
}
};
Surely what you are attempting to do is as simple as:
std::function<void()> f = [this, arg1, arg2]() {
ios_.post([this, arg1, arg2]() {
this->func(arg1, arg2);
});
};
now your thread can call f(), which will do the right thing...
Or am I missing something...
Related
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.
I've implemented a factory pattern in C++ some weeks ago using the following guide : https://www.codeproject.com/Articles/363338/Factory-Pattern-in-Cplusplus
Since then it worked well: all of the methods used in the factory pattern were returning the same type, and were also taking the same arguments types, until today. I now need to add bind new arguments to the methods I use, so methods signatures are not the same anymore.
I am currentyl using 2 things, and implementing a third one :
1) Actions: each represented as a class and containing a static AAction::ptr create(void* buff) method. Actions inherits from AAction class. Actions can be serialized using their own serialize() internal method, or deserialized using their create(buff) static method.
The buffer argument contains the id and password necessary to call the LoginAction() constructor.
class AAction {
typedef std::unique_ptr<AAction> ptr;
};
class LoginAction : public AAction {
private:
std::string id;
std::string password;
bool authenticated;
public:
LoginAction(std::string id, std::string password);
virtual ~LoginAction() = default;
void execute();
static AAction::ptr create(const void* buffer);
};
2) ActionFactory: used to deserialize incoming actions, by calling the appropriate create() static method from the correct class.
class ActionFactory {
typedef std::unique_ptr<AAction> (*CreateActionFn)(const void*);
typedef std::map<RawActionType, CreateActionFn> RawFactoryMap;
RawFactoryMap rawFactoryMap;
public:
ActionFactory(Authenticator& authenticator) {
this->registerMethod(RawActionType_RawLoginAction, &LoginAction::create);
this->registerMethod(RawActionType_RawLogoutAction, &LogoutAction::create);
this->registerMethod(RawActionType_RawStandAction, &StandAction::create);
}
void registerMethod(const RawActionType &rawActionType, CreateActionFn pfnCreate);
std::unique_ptr<AAction> getAction(RawActionType rawActionType, const void* buffer);
};
Actions can be executed at any time in the code, by simply calling the execute() method, with no parameters.
Up to this point, eveything works fine.
The issue is that I now need to add some more parameters to actions that are not stored inside the password. For example in my case: an Authenticator
3) An Authenticator, to authenticate a user.
So that inside LoginAction::execute(), all I have to do is call
this->authenticator.authenticate(this->id, this->password).
Here are the changes I made for that :
I added authenticator to the LoginAction constructor :
LoginAction(Authenticator& authenticator, std::string id, std::string password);
And a field :
Authenticator& authenticator;
I added authenticator to the LoginAction::create static method :
static AAction::ptr create(const void* buffer, Authenticator& authenticator);
I modified, inside the ActionFactory constructor, the way I register method, using std::bind :
this->registerMethod(RawActions_RawLoginAction, std::bind(&LoginAction::create, std::placeholders::_1, authenticator);
But, as my function types have changed, I cannot store it in the RawFactoryMap anymore.
error: invalid cast from type ‘std::_Bind_helper ()(const void, Authenticator&), const
std::_Placeholder<1>&, Authenticator&>::type {aka
std::_Bind ((std::_Placeholder<1>,
Authenticator))(const void, Authenticator&)>}’ to type
‘ActionFactory::CreateActionFn {aka std::unique_ptr ()(const
void)}’
What is the best way to proceed, to keep a map of functions in the ActionFactory and respect the Factory pattern ?
Thanks in advance, and have a good day!
As an additional note: I am open and would be glad to read any suggestion on how to improve my code, even for some minor improvements.
First things first. With C++11, strongly prefer using to typedef. Consider the difference in readability between:
typedef std::unique_ptr<AAction> (*CreateActionFn)(const void*);
typedef std::map<RawActionType, CreateActionFn> RawFactoryMap;
and:
using CreateActionFn = std::unique_ptr<AAction>(*)(const void*);
using RawFactoryMap = std::map<RawActionType, CreateActionFn>;
It's nice when the names appear on the left instead of in an arbitrary location.
That said, now that function pointers are insufficient because you need to store state, you need to generalize to an arbitrary callable. That's what std::function is for: a type-erased callable of the provided signature:
using CreateActionFn = std::function<std::unique_ptr<AAction>(const void*)>;
This will match any callable that is copyable and which you can invoke with a const void* and get a unique_ptr<AAction>.
And while we're here, don't use std::bind:
std::bind(&LoginAction::create, std::placeholders::_1, authenticator)
use a lambda:
[authenticator](void const* ptr){ return LoginAction::create(ptr, authenticator); }
or:
[=](void const* ptr){ return LoginAction::create(ptr, authenticator); }
It may not be shorter, but it's quite a bit easier to read.
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.
I would like to use boost::shared_ptr<> to encapsulate the lifetime management of a handle. My handle and it's creation/destruction functions are declared like this:
typedef const struct MYHANDLE__ FAR* MYHANDLE;
void CloseMyHandle( MYHANDLE );
MYHANDLE CreateMyHandle();
Ideally, I would like to use the boost::shared_ptr<> like this to manage the handle:
boost::shared_ptr< void > my_handle( CreateMyHandle(), &CloseMyHandle );
Unfortunately, because the handle is declared as a const struct * instead of the usual void *, I get errors like this:
boost/smart_ptr/shared_ptr.hpp(199) : error C2440: 'initializing' : cannot convert from 'const MYHANDLE__ *' to 'void *'
I can use a functor to cast the void * to a MYHANDLE like this:
struct DeallocateMyHandle
{
void operator()( void* handle )
{
CloseMyHandle( ( MYHANDLE )handle );
};
};
boost::shared_ptr< void > my_handle( ( void* )CreateMyHandle(), DeallocateMyHandle() );
But, I'd rather have a method that doesn't involve the separate functor. Is there a way to do this just within the boost::shared_ptr<> constructor that I'm not seeing? Or, am I stuck with the functor?
Thanks,
PaulH
Why not use:
boost::shared_ptr< const MYHANDLE__ > my_handle( CreateMyHandle(), &CloseMyHandle );
PS. Note the use of double underscore is not allowed (it is reserved for the implementation).
See: Rules about identifers
If HANDLE is a public type, but the type it points to is not, there's a really easy way to write this:
template <typename T> struct unpointer { };
template <typename T> struct unpointer<T*> { typedef T type; };
boost::shared_ptr<typename unpointer<MYHANDLE>::type> my_handle(
CreateMyHandle(), &CloseMyHandle);
(If you're using a really old version of VC++ or gcc you probably have to omit the "typename" there.)
Of course this gets a bit verbose and tedious. If you're only got one handle type to deal with, you probably to write this:
typedef typename unpointer<MYHANDLE>::type MYHANDLEREF;
typedef boost::shared_ptr<MYHANDLEREF> my_shared_ptr;
If you've got all kinds of handles to wrap (and since it looks like you're doing Win32 API stuff, you probably do), create a template that wraps things up at whatever level you prefer (a class template that just generates the types, a handle_ptr<T> that subclasses shared_ptr<unpointer<T>> and adds the default deleted for you, a handle_ref<T> that uses a shared_ptr behind the scenes to fake being a MYHANDLE & instead of faking being what MYHANDLE is a pointer to, etc.)
Your shared_ptr type needs to be this:
boost::shared_ptr< const MYHANDLE__ FAR>
That way when shared_ptr makes a pointer out of it, it becomes:
const MYHANDLE__ FAR*
Which matches your MYHANDLE type exactly:
#include <boost/shared_ptr.hpp>
struct MYHANDLE__ {};
typedef const MYHANDLE__* MYHANDLE;
void CloseMyHandle(MYHANDLE) {}
MYHANDLE CreateMyHandle(void) { return 0; }
int main()
{
typedef boost::shared_ptr<const MYHANDLE__> ptr_type;
ptr_type my_handle( CreateMyHandle(), &CloseMyHandle );
}
Note, I really doubt you need FAR, that's from the 16-bit ages. It expands to either far or nothing, depending on if you're compiling for 16-bit (hint: you aren't compiling to 16-bit. :) ). far isn't even an extension anymore, as far as I know.
Also, like Martin said don't use double-underscores anywhere.
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