I'm trying to create a simple Signals/Slots system in C++ without boost but I've got some problems when I try to use it with parameters, here is my code :
My Signal class :
template <typename T>
class Signal
{
private:
typedef std::function<T> Slot;
public:
Signal();
void connect( Slot slot );
void emit( T data );
void emit();
private:
std::vector<Slot> slots;
};
My Test class :
class Object
{
public:
Object();
void sayHello( int i );
};
So, I use my class like that :
Signal<void(int)> signal;
signal.connect( std::bind( &Object::sayHello, player, std::placeholders::_1 ) );
signal.emit( 0 );
I've got a warning in Signal.cpp : Candidate function not viable: no known conversion from 'void (*)(int)' to 'int' for 1st argument;
In this code :
template <typename T>
void Signal<T>::emit( T data )
{
typename std::vector<Slot>::iterator i;
Slot t;
for( i = this->slots.begin(); i != this->slots.end(); i++ )
{
t = (*i);
t( data ); // Here
}
}
How can I solve that? If I want give an object or multiples parameters to my "emit" method, hoc can i do?
Thanks!
A slot is called when a signal connected to it is emitted. Slots are normal C++ functions and can be called normally; their only special feature is that signals can be connected to them. A slot's arguments cannot have default values, and, like signals, it is rarely wise to use your own custom types for slot arguments.
In Qt, we have an alternative to the callback technique: We use signals and slots. A signal is emitted when a particular event occurs. Qt's widgets have many predefined signals, but we can always subclass widgets to add our own signals to them. A slot is a function that is called in response to a particular signal.
Picking three lines from your Signal
class:
template <typename T>
// ...
typedef std::function<T> Slot;
// ...
void emit( T data );
And the declaration of your signal:
Signal<void(int)> signal;
The answer should be pretty obvious: void emit(T)
becomes void emit(void(*)(int))
(function types like void(int)
transform to pointers when they are function parameters).
I'd simply recommend going the same way every class template that uses T<Signature>
goes: partial specialization.
template<class Sig>
class Signal;
template<class R, class... Args>
class Signal<R(Args...)>{
// ...
typedef std::function<R(Args...)> Slot;
// ...
void emit(Args... args) const{
// iterate over slots and call them, passing `args...`
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With