Skip to content

Instantly share code, notes, and snippets.

@pfirsich
Created August 22, 2016 10:23
Show Gist options
  • Save pfirsich/b26285ae4f76706759321c29d076603a to your computer and use it in GitHub Desktop.
Save pfirsich/b26285ae4f76706759321c29d076603a to your computer and use it in GitHub Desktop.
Signals/Slots
#ifndef __SIGNAL_HPP_INCLUDED__
#define __SIGNAL_HPP_INCLUDED__
#include <cstdio>
#include <vector>
#include <functional>
// eraz on ##c++@freenode helped me with this, by pointing me to std::function!
// Here we use std::function like template syntax, by defining a generic Signal and
// using template specialization to extract the return and argument types of the single
// function pointer type that's passed
template<class T>
class Signal;
template<class returnType, class... argTypes>
class Signal<returnType (argTypes...)> {
public:
// We use std::function so we can use both static functions and member functions, that we bind using
// lambdas, that we cannot directly cast to a function pointer
using slotType = std::function<returnType(argTypes...)>;
private:
std::vector<slotType> mSlots;
public:
void connect(slotType slot) {
mSlots.push_back(slot);
}
template<class objType>
void connect(objType* obj, returnType (objType::*slot)(argTypes...)) {
// [=] i.e. capture by value is necessary
// if capture by reference is used obj will be captured from the stack of connect
// this will result in a segfault
auto f = [=](argTypes... args) -> returnType {return (obj->*slot)(args...);};
mSlots.push_back(f);
}
returnType emit(argTypes... args) {
returnType ret;
for(auto slot : mSlots) {
printf("slot");
ret = slot(args...);
}
printf("done\n");
return ret;
}
};
#endif
/*
int someSlot(float a, int b, float c) {
printf("slot: %f, %d, %f\n", a, b, c);
return 5;
}
class ListenClass {
public:
int listenSlot(float a, int b, float c) {
printf("listenslot: %f, %d, %f\n", a, b, c);
return 4;
}
};
int main(int argc, char** argv) {
using SomeSignalType = Signal<int(float, int, float)>;
SomeSignalType someSignal;
someSignal.connect(someSlot);
ListenClass listener;
auto f = [&](float a, int b, float c) -> int {return listener.listenSlot(a, b, c);};
someSignal.connect(f);
someSignal.connect(&listener, ListenClass::listenSlot);
printf("ret: %d", someSignal.emit(1.0f, 2, 2.0f));
return 0;
}
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment