Я пытаюсь создать простую систему Сигналы / Слоты в C ++ без повышения, но у меня есть некоторые проблемы, когда я пытаюсь использовать ее с параметрами, вот мой код:
Мой Сигнал класс:
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;
};
Мой тестовый класс:
class Object
{
public:
Object();
void sayHello( int i );
};
Итак, я использую свой класс так:
Signal<void(int)> signal;
signal.connect( std::bind( &Object::sayHello, player, std::placeholders::_1 ) );
signal.emit( 0 );
Я получил предупреждение в Signal.cpp:
Функция-кандидат недопустима: нет известного преобразования из ‘void (*) (int) «в» int «для 1-го аргумента;
В этом коде:
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
}
}
Как я могу решить это? Если я хочу дать объект или несколько параметров для моего метода «излучать», я могу это сделать?
Спасибо!
Выбрав три строки из вашего Signal
учебный класс:
template <typename T>
// ...
typedef std::function<T> Slot;
// ...
void emit( T data );
И объявление вашего сигнала:
Signal<void(int)> signal;
Ответ должен быть довольно очевидным: void emit(T)
становится void emit(void(*)(int))
(типы функций, такие как void(int)
преобразовывать в указатели, когда они являются параметрами функции).
Я бы просто рекомендовал делать так же, как каждый шаблон класса, который использует T<Signature>
идет: частичная специализация.
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...`
}
};
Других решений пока нет …