I'm working on an event system. Basically there are "slots" which any member can chime into. All they need is an event name which it will be listening to, and a function. Since all the slots are stored I had to store them as a variable in a class.
The function becomes unavailable when it's placed into the SlotBase class. I am wondering if there is a way to retain the function in the Slot class while storing in in the SlotBase class.
class SlotBase { };
// TC - Template Class
// TA - Template Arguments (types)
template <class TC, typename ...TA>
class Slot : public SlotBase {
public:
Slot(TC* funcClass, void(TC::*func)(TA...)) {
SetSlot(funcClass, func);
}
template <int ...Is>
void SetSlot(TC* funcClass, void(TC::*func)(TA...), int_sequence<Is...>) {
function = std::bind(func, funcClass, placeholder_temp<Is>{}...);
}
void SetSlot(TC* funcClass, void(TC::*func)(TA...)) {
SetSlot(funcClass, func, make_int_sequence<sizeof...(TA)>{});
}
std::function<void(TA...)> returnFunction(){
return function;
}
private:
std::function<void(TA...)> function;
};
//...
class RandomClass {
public:
void randomFunction(int a, float b, int c){ //do stuff };
}
//...
RandomClass randC;
SlotBase baseS;
Slot newSlot(&randC, &RandomClass::randomFunction);
baseS = newSlot;
//...
//Later on down the line when an event was found matching slot call slot function
baseS.returnFunction()(//Correct arguments go here - leaving this out (a lot more code));
I didn't include the code for the integer sequences in the 'std::bind' as it isn't related to the problem.
I know that if I use a Slot cast on the baseS
variable that would give me the result but I am unable to do so because I don't know the templates that Slot will have.
I have seen many similar posts stating to make baseS
a pointer (such as here ) but I still don't understand how you would grab the function.
I think you need to start to accept that at some point if you want to use polymorph objects, you will need to create a virtual function in SlotBase
. If you want to cast back to your type at creation before using the function, the polymorphism makes no sense, because you have carried the original type somewhere along with you to be able to do so, so why upcast anyway in the first time ?
If you really need to upcast, then you need to think about a RUNTIME solution to get back to access the derived functionality. In this case, this would mean you need to create a generic interface to your signals, so try to make a pure virtual method in SlotBase
that will pack an undefined number of arguments, and implement that generic caller in your Slot
so that it unpacks the arguments in order and calls your slot with the arguments. I don't know if variadic methods can be overriden though, that seems dubious. Otherwise you'll have to use boost::any or something to pack the arguments in a runtime collection.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.