Skip to content

Instantly share code, notes, and snippets.

@r2p2
Created July 20, 2011 14:43
Show Gist options
  • Save r2p2/1095090 to your computer and use it in GitHub Desktop.
Save r2p2/1095090 to your computer and use it in GitHub Desktop.
Xer Signalklasse
#include <iostream>
#include <vector>
struct CallbackNoArg
{
};
class CallbackBase
{
public:
virtual void operator()(void *arg0 = 0,
void *arg1 = 0,
void *arg2 = 0) = 0;
};
template <class T, class Arg0 = CallbackNoArg,
class Arg1 = CallbackNoArg,
class Arg2 = CallbackNoArg>
class Callback : public CallbackBase
{
public:
Callback(T &object, void (T::*method0)())
:CallbackBase()
,m_object(object)
,m_method0(method0)
,m_argc(0)
{
}
Callback(T &object, void (T::*method1)(Arg0))
:m_object(object)
,m_method1(method1)
,m_argc(1)
{
}
Callback(T &object, void (T::*method2)(Arg0, Arg1))
:m_object(object)
,m_method2(method2)
,m_argc(2)
{
}
Callback(T &object, void (T::*method3)(Arg0, Arg1, Arg2))
:m_object(object)
,m_method3(method3)
,m_argc(3)
{
}
virtual void operator()(void *arg0 = 0,
void *arg1 = 0,
void *arg2 = 0)
{
switch(m_argc)
{
case 0:
(m_object.*m_method0)();
break;
case 1:
(m_object.*m_method1)(*reinterpret_cast<Arg0*>(arg0));
break;
case 2:
(m_object.*m_method2)(*reinterpret_cast<Arg0*>(arg0),
*reinterpret_cast<Arg1*>(arg1));
break;
case 3:
(m_object.*m_method3)(*reinterpret_cast<Arg0*>(arg0),
*reinterpret_cast<Arg1*>(arg1),
*reinterpret_cast<Arg2*>(arg2));
break;
}
}
private:
T &m_object;
void (T::*m_method0)();
void (T::*m_method1)(Arg0);
void (T::*m_method2)(Arg0, Arg1);
void (T::*m_method3)(Arg0, Arg1, Arg2);
unsigned int m_argc;
};
template <class Arg0 = CallbackNoArg,
class Arg1 = CallbackNoArg,
class Arg2 = CallbackNoArg>
class Signal
{
struct data_t
{
CallbackBase* cb;
bool dynamic;
};
public:
Signal()
:m_callbacks()
{
}
~Signal()
{
unsigned int size = m_callbacks.size();
for(unsigned int i = 0; i < size; ++i)
{
delete m_callbacks[i];
}
}
template<class T>
void register_callback(T &object, void (T::*method)())
{
m_callbacks.push_back(new Callback<T>(object, method));
}
template<class T>
void register_callback(T &object, void (T::*method)(Arg0))
{
m_callbacks.push_back(new Callback<T, Arg0>(object, method));
}
template<class T>
void register_callback(T &object, void (T::*method)(Arg0, Arg1))
{
m_callbacks.push_back(new Callback<T, Arg0, Arg1>(object, method));
}
template<class T>
void register_callback(T &object, void (T::*method)(Arg0, Arg1, Arg2))
{
m_callbacks.push_back(new Callback<T, Arg0, Arg1, Arg2>(object, method));
}
// ACHTUNG: hier werden die Argumente nicht als Referenz übergeben. Geht das irgenwie sinnvoll?
// ok, man könnte emit_signal auch überladen
void emit_signal(Arg0 arg0 = CallbackNoArg(), Arg1 arg1 = CallbackNoArg(), Arg2 arg2 = CallbackNoArg())
{
unsigned int size = m_callbacks.size();
for(unsigned int i = 0; i < size; ++i)
{
(*(m_callbacks[i]))(reinterpret_cast<void*>(&arg0), reinterpret_cast<void*>(&arg1), reinterpret_cast<void*>(&arg2));
}
}
private:
Signal(Signal const &orig);
std::vector<CallbackBase*> m_callbacks;
};
class Timer
{
public:
Timer()
:m_pcb(0)
{
}
template<class T>
void registerCallback(T &cb)
{
m_pcb = &reinterpret_cast<CallbackBase&>(cb);
}
void useCallback(int x)
{
(*m_pcb)(reinterpret_cast<void*>(&x));
}
void useCallback(double a, double b)
{
(*m_pcb)(reinterpret_cast<void*>(&a),reinterpret_cast<void*>(&b));
}
private:
CallbackBase *m_pcb;
};
class Example
{
public:
void foo()
{
std::cout << "hello world" << std::endl;
}
void inc(int arg0)
{
std::cout << "inc: " << arg0+1 << std::endl;
}
void add_two(int arg0)
{
std::cout << "add 2: " << arg0+2 << std::endl;
}
void call2(double a, double b)
{
std::cout << "hi: " << a/b << std::endl;
}
};
int main()
{
Example e;
Signal<int> s;
s.register_callback(e, &Example::inc);
s.register_callback(e, &Example::add_two);
s.emit_signal(5);
Signal<> s2;
s2.register_callback(e, &Example::foo);
s2.emit_signal();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment