Basically I need to implement an event handler class, but run into an error that I cannot declare an array of voids:
class SomeClass
{
public:
void registerEventHandler(int event, void (*handler)(std::string));
private:
// here i get this error: declaration of ‘eventHandlers’ as array of void
void (*eventHandlers)(std::string)[TOTAL_EVENTS];
}
void SomeClass::registerEventHandler(int event, void (*handler)(std::string))
{
eventHandlers[event] = handler;
}
void handler1(std::string response)
{
printf("ON_INIT_EVENT handler\n");
}
void handler2(std::string response)
{
printf("ON_READY_EVENT handler\n");
}
void main()
{
someClass.registerEventHandler(ON_INIT_EVENT, handler1);
someClass.registerEventHandler(ON_READY_EVENT, handler2);
}
Can you help me figure out the exact syntax?
Thanks!
This is not array of voids. It's array of function pointers.
You should have defined it as follows:
void (*eventHandlers[TOTAL_EVENTS])(std::string);
Or better (C++14):
using event_handler = void(*)(std::string);
event_handler handlers[TOTAL_EVENTS];
Or C++03:
typedef void(*event_handler)(std::string);
event_handler handlers[TOTAL_EVENTS];
But I would rather recommend to do it using vector:
using event_handler = void(*)(std::string);
std::vector<event_handler> handlers;
You are defining eventHandles as a pointer to a function returning an array of 5 voids, which is not what you intended.
Instead of trying to do this in one line, it will be easier and more readable by using a typedef:
typedef void (*event_handler_t)(std::string);
event_handler_t eventHandlers[TOTAL_EVENTS];
You mixed the event handler type and the array definition. Separate with typedef:
typedef void(*eventHandler)(std::string);
eventHandler eventHandlers[TOTAL_EVENTS];
Related
I'm attempting to create a tuple which contains a pointer to a void member function, but I'm having trouble making it work.
here's my code:
class A
{
void dostuff(){ cout<<" doing stuff "}
};
class B
{
A* aobj;
typedef vector<vector<tuple<int,int,void(A::*)()>>> sequence;
sequence Sequence;
void getinfo(int n1, int n2, void(A::*func)())
{
Sequence.resize(1);
Sequence[0].push_back(make_tuple(n1,n2,(aobj->*func)()))//<--ERROR HERE
};
};
it's giving me the error "invalid use of void expression."
I also tried to simplify the function to :
void getinfo(void(A::*func)())
{
make_tuple((aobj->*func)());
}
and it still gives me the same error.
As Igor Tandetnik pointed out, (aobj->*func)() was calling the method and returning void to the make_tuple() function. To pass a member pointer, it should instead be make_tuple(n1,n2,func).
I am trying to implement a generic event handling system with templates, but I get an error at compile time when I try to add the function to a list.
error C2298: missing call to bound pointer to member function
class EventManager
{
public:
template <class OBJECT>
void subscribe(std::string eventName, OBJECT *obj, void(OBJECT::*newEvent)(Event))
{
(obj->*newEvent)(Event()); // I can call the event just fine if I execute it alone
abc.push_back(obj->*newEvent); // Error c2298 here
}
static EventManager* Get();
private:
std::vector<void(*)(Event)> eventsList;
};
And this is where I call it:
EventManager::Get()->subscribe("EventName", this, &TestClass::eventTest);
void ATideManager::eventTest(Event event)
{
//Test
}
I am quite new to C++ and templates, so I'm sure the solution is easy, but I don't understand why I can call the event but not add it to the vector. Do you know how I could possibly do that?
As the documentation for that error message says:
A pointer to member-function expression must call the member function.
In other words, you cannot store a pointer to member-function including the object on which to call it, for later use.
Here is a simpler example using names similar to yours:
struct Object
{
void f() {}
};
int main()
{
Object obj;
using member_function_pointer = void (Object::*)();
member_function_pointer ptr = &Object::f;
(obj.*ptr)();
(obj.*ptr); // error
}
And this makes a lot of sense. Your abc is probably a vector of pointers to member-function (or just a vector of function pointers); it cannot magically store an object along with each pointer in it.
Generally, pointers to member functions are not exactly the nicest, cleanest or best feature of C++, and the awful syntax renders every piece of code using it completely unreadable. Fortunately, C++11 introduced std::function and lambdas, which gives you a much better alternative:
#include <functional>
#include <iostream>
#include <string>
#include <vector>
struct Event
{
int i;
};
class EventManager
{
public:
void subscribe(std::string const& eventName,
std::function<void(Event const&)> event)
{
abc.push_back(event);
}
static EventManager& get()
{
static EventManager instance;
return instance;
}
void onEvent(Event const& event)
{
for (auto&& f : abc)
{
f(event);
}
}
private:
EventManager() {}
EventManager(EventManager const&) = delete;
EventManager& operator=(EventManager const&) = delete;
std::vector<std::function<void(Event const&)>> abc;
};
struct ATideManager
{
void f()
{
EventManager::get().subscribe("EventName",
[=](Event const& event) { eventTest(event); });
}
void eventTest(Event const& event)
{
std::cout << "eventTest: " << event.i << "\n";
}
};
int main()
{
ATideManager manager;
manager.f();
Event some_event{ 123 };
EventManager::get().onEvent(some_event);
}
I've also fixed your needless use of pointers where references can be used, and some const-correctness issues.
obj->*newEvent is invalid. A member function pointer can be used in this way only to call the pointed-to member function.
You can however use std::vector<std::function<void(Event)>> and
abc.push_back(std::bind(newEvent, obj, std::placeholders::_1);
std::bind reference
I have a player class which looks like this (stripped down to what is needed for this problem):
class Player
{
public:
Player();
~Player();
void kill();
void death();
void reset();
};
The kill(), death(), and reset() functions look like this:
void Player::kill()
{
void (*dPtr)() = &death;
Game::idle(dPtr, 48);
}
void Player::death()
{
reset();
}
void Player::reset()
{
//resets
}
The idle function is a static memeber function of Game, which takes a function pointer and an integer n, and calls the function after n tick. Here is the function, the implementation shouldn't matter:
class Game {
static void idle(void (*)(), int);
};
This code gives me the error:
ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say '&Player::death' [-fpermissive]
So I change the line from
void (*dPtr)() = &death;
to
void (Player::*dPtr)() = &Player::death;
to solve that issue. But then my call to the idle function is incorrect, as it takes a regular function pointer, and I am passing in a member function pointer, and thus gives me the error:
no matching function for call to 'Game::idle(void (Player::*&)(), int)'
So my question is:
How can I pass the member function pointer Player::*dPtr into the idle function, which takes a void (*)() as an argument?
Or is there another way I can solve my previous error which forbids me from taking the address of an unqualified member function to form a pointer to a member function?
Another answer mentions that you need two pointers. However C++ already comes with containers for doing just this, so it would make your code a lot simpler to use those. (In C++03, some of the std:: items below were std::tr1::).
Sample code:
#include <iostream>
#include <functional>
struct Game
{
static void idle( std::function<void()> func, int x )
{ std::cout << "x = " << x << "\n"; func(); }
};
struct Player
{
void death() { std::cout << "player.death\n"; }
void kill() { Game::idle( std::bind(&Player::death, this), 48 ); }
};
int main()
{
Player p;
p.kill();
}
Lifetime note: std::bind binds by value. Using *this means a copy of the Player is made and stored in the std::function object, copied around with it as necessary.
Using this means the function object stores a pointer, so if you actually store the function object in Game::idle you must take care that this Player is not destroyed before removing this function object from Game::idle's list.
To call a member function through a pointer, you need two pointers: the pointer to the function itself, and a pointer to an object to be this. Your Game::idle API does not support this usage. You need to change it so that it passes at least one argument (conventionally of type void *) to the callback. Then you can use the following pattern:
struct Player
{
// ...
void kill();
// ...
static void call_kill(void *self);
};
void Player::call_kill(void *self)
{
static_cast<Player *>(self)->kill();
}
struct Game
{
static void idle(void (*)(void *), void *, int);
};
void Game::idle(void (*callback)(void *), void *arg, int ticks)
{
// ...
callback(arg);
// ...
}
void kill_player_delayed(Player *p, int ticks)
{
Game::idle(Player::call_kill, static_cast<void *>(p), ticks);
}
You have to write a static call_X method for every instance method X you want to call.
An alternative approach, which is arguably more C++-idiomatic and flexible, and involves less explicitly written-out code, but has higher runtime costs (three indirect function calls and a heap allocate-free cycle per invocation, instead of a single indirect function call), is to have Game::idle take an object of a particular class, with a virtual callback method. That class is then given a template subclass that can call anything that implements operator(), such as the result of std::bind.
struct Runnable { virtual ~Runnable(); virtual void invoke() = 0; };
template <typename T> struct TRunnable : Runnable {
TRunnable(T target) : target(target) {}
void invoke() { target(); }
private:
T target;
};
template <typename T> TRunnable<T>* make_Runnable(T obj)
{ return new TRunnable<T>(obj); }
struct Game
{
static void idle(Runnable *, int);
};
void Game::idle(Runnable *r, int ticks)
{
// ...
r->invoke();
delete r;
// ...
}
struct Player
{
// ...
void kill();
// ...
};
void kill_player_delayed(Player *p, int ticks)
{
Game::idle(make_Runnable(std::bind(&Player::kill, p)), ticks);
}
You cannot make Game::idle take the result of std::bind directly because that object's type is unspecified (and varies depending on how you call std::bind), so it can only be used as an argument to a template function call. A virtual method call to an adapter class is the only way to keep Game::idle compiled out-of-line and still let it use bound-call objects.
In either approach, beware object lifetime issues. In particular, if Game::idle does not call its callback before returning, you need to
make sure that both the original object, and (in the second approach)
the object returned by make_Runnable survive until the callback fires. This is why make_Runnable uses new.
Because I really don't like the answer that casts void*'s to other objects (almost never necessary in C++!) and nobody has posted an answer using the suggestions in the comments I'm going to suggest this.
Use a templated type for your callback!
Like this:
class Game{
template<typename Func>
static void idle(Func &&func, int i){
// game stuff
func();
// other game stuff
}
};
Then you don't lose all of your type safety (casting void*) and it should be the fastest solution.
Also, where you are assigning a function pointer, you can change the code to be far more readable in this case:
void Player::kill(){
Game::idle([this](){this->death();}, 48);
}
Which is far nicer than having to write the correct function pointer type.
You cannot do that simply because pointer to [static] function is a single pointer sizeof void*. In contrary member function need more information, e.g. two pointers: one for this and another one for the function itself so member function pointer has sizeof > sizeof(void*).
Therefore you have two options:
to change signature of your idle() to this void idle(void (*)(), void*, int); so you will be able to pass this somehow.
Or make static variable that will hold this pointer. But that assumes that only one death() can be at idle queue at any given moment of time.
1) is what people do usually in such cases.
I'm trying to write a program which creates a class that contains vector of pointers to member functions, with add() and remove() member functions.
The code I wrote is -
#include <iostream>
#include <vector>
using namespace std;
typedef void(*classFuncPtr)();
class FunctionVectors
{
private:
vector<classFuncPtr> FunctionPointerVector;
public:
FunctionVectors(){}
void add(classFuncPtr funcPtr);
void remove(int index);
void run();
void a(){cout<<"a: Why are you calling me?"<<endl;}
};
void FunctionVectors::add(classFuncPtr funcPtr)
{
FunctionPointerVector.push_back(funcPtr);
}
void FunctionVectors::remove(int index)
{
FunctionPointerVector.erase(FunctionPointerVector.begin() + index);
}
int main()
{
FunctionVectors f;
classFuncPtr fv = &(classFuncPtr)FunctionVectors::a; // error here
f.add(fv);
f.run();
return 0;
}
But, it is showing error in line# 32 -
error C2440: 'type cast' : cannot convert from 'void (__thiscall FunctionVectors::* )(void)' to 'classFuncPtr'
Please, tell me how should I modify it to work properly.
typedef void(*classFuncPtr)();
This is not a pointer to method, but a pointer to function. Method differs from function, because it's being called in a context: requires this to work correctly.
Keep in mind, that in C++ you are only able to create vector of pointers to a method of specific class. So you won't be able to keep pointers to two methods of different classes in that vector.
The solution - as suggested in comments - is to use std::function or boost::function and possibly C++11 lambdas, because they provide a lot more flexibility than simple pointer-to-members.
If you want to implement an event mechanism, consider also using functors instead of methods:
Create base class for event handler:
class MyEventHandler
{
public:
virtual void operator()(void * sender, int data) = 0;
}
Create simple vector of these:
std::vector<MyEventHandler *> MyEvent;
Create specific handlers in your classes:
class MyClass
{
private:
class SpecificEventHandler : MyEventHandler
{
public:
void operator()(void * sender, int data)
{
std::cout << "Event handled!";
}
}
public:
SpecificEventHandler Handler;
MyClass()
{
}
}
Hook the handler to your event:
MyEvent.push_back(&(myClassInstance.Handler));
Code written from memory, may not compile, but you should get the idea.
std::function< void() >
looks like the signature you are looking for. If it isn't available in your version of C++ but you can use boost, then you fill find it in boost. Look up documentation for appropriate header, for std, for function.
To create one for a member function, you need to bind it, and to bind it to FunctionVectors::a() you will need an instance of a FunctionVectors to call it on.
In your example, I will make the typedef for you
typedef std::function< void() > classFuncPtr; // in reality a badly named typedef
int main()
{
FunctionVectors f;
classFuncPtr fv = std::bind( &FunctionVectors::a, f );
}
alternatively if you really have C++11 with lambdas you can do
classFuncPtr = [ f ]() { f.a() );
In your case I reckon you don't really want a free function, you always want a member function of your class you want.
typedef void (*FunctionVectors::classFuncPtr )();
and you would use
(this->*func)();
to invoke it
MyClass is a singleton class (There will only ever be one of these in my whole program).
What I want to do is follows.
Add data to my class using AddData, get a function pointer returned that I can then pass to 'another' function in a dll.
Then this 'other' function calls my call back function
My class is like so.
typedef void (*DataReceivedCallback)(int, int);
class MyClass
{
MyClass();
~MyClass();
void AddData(int sourceId, DataReceivedCallback &callback);
static void MyCallBackFunction(int var1, int var2);
};
void MyClass::AddData(int sourceId, DataReceivedCallback &callback)
{
callback = &MyCallBackFunction;
}
void MyClass::MyCallBackFunction(int var1, int var2 )
{
//do something blah blah
}
I can then do:
int main()
{
DataReceivedCallback callback;
MyClass->GetInstance()->AddData(1, callback);
callback(1,100);
}
When I step through this I see that I do actually step into the callback MyCallBackFunction which is what I want :)
What I then want to do now is pass this 'callback' defined in main to a dll function that will call back into my callback function.
I have the code for the dll so I want to modify one if its functions so that it accepts my callback function parameter.
I am doing this in the dll function signature:
void * someDllFunction( int var1, int var2, DataReceivedCallback& callback)
{
callback(2, 200);
}
But I get the error:
error C2872: 'DataReceivedCallback' : ambiguous symbol
How can I solve this?
Does this have to do with only being allowed to use c-style parameters across dll boundaries??
typedef void (*DataReceivedCallback)(int, int);
should be,
typedef void (MyClass::*DataReceivedCallback)(int, int);
Because, MyCallBackFunction is a non-static member method of MyClass. So it cannot have regular function signature.
Also change assignment to,
callback = &MyClass::MyCallBackFunction;
Demo.
You got your types wrong. DataReceivedCallback, alias void(*)(int, int), is a function pointer, but &MyClass::MyCallBackFunction is a pointer-to-member-function (PTMF). Those two are entirely unrelated and incompatible types!
You cannot treat a member function as a free function.
Since you only have one single instance of your class (Note: "one instance", not "one class"; you always only have one class), why bother with member functions at all? Just make the function global (inside a namespace) and you're done. Though perhaps I'm misunderstanding your requirements.
Another note: You don't need to pass function pointers by reference to the DLL function, just pass them by value. They're just pointers, so they're light-weight.
The thing you are missing is how to declare a pointer to member function and how to invoke the member function via that pointer, below is a working example based on your example:
class MyClass;
//standard way to declare a pointer to member function should be - className::*memberFunName(para list)
typedef void (MyClass::*DataReceivedCallback)(int, int);
class MyClass
{
public:
void AddData(int sourceId, DataReceivedCallback &callback);
void MyCallBackFunction(int var1, int var2);
};
void MyClass::AddData(int sourceId, DataReceivedCallback &callback)
{
callback = &MyClass::MyCallBackFunction;
}
void MyClass::MyCallBackFunction(int var1, int var2 )
{
//do something blah blah
int tem = var1 + var2; //tem = 3 here
}
int main()
{
MyClass obj;
DataReceivedCallback callback;
obj.AddData(1, callback);
(obj.*callback)(1,2); //standard way to call the member function via function pointer
}