来自 https://gitee.com/jiang_xu_hui/tan-meta-object
TanMetaObject
介绍
80行代码实现Qt信号槽机制。
去除无用行估计也就40行。
使用说明
- 仿Qt的信号槽,本来打算用c++20的概念和约束来写,但是国内根本没有普及c++20,最后还是用了c++11.
- main.cpp内有使用的例子。
TanMetaObject.h
#include <vector>
#include <utility>
template<typename T, typename ...Args>
using signal_function = void(T::*)(Args...);
template <typename ...Args>
struct TanSlotBase
{
virtual void run(Args...) = 0;
};
template<typename T, typename ...Args>
class TanSlot : public TanSlotBase<Args...>
{
public:
TanSlot(T* class_ptr, signal_function<T, Args...> slot_func_ptr)
: class_ptr(class_ptr), slot_func_ptr(slot_func_ptr){}
bool operator==(T* ptr)
{
return class_ptr == ptr;
}
bool operator==(signal_function<T, Args...> func)
{
return slot_func_ptr == func;
}
private:
virtual void run(Args... args) final
{
(class_ptr->*slot_func_ptr)(args...);
}
private:
T* class_ptr;
signal_function<T, Args...> slot_func_ptr;
};
template< typename...Args>
class TanSignal
{
public:
using slot_func = void(*)(Args...);
public:
std::vector<TanSlotBase<Args...>*> _slots;
void emit(Args... args)
{
for(auto slot : _slots)
{
slot->run(args...);
}
}
~TanSignal(){
for(auto slot : _slots)
{
delete slot;
}
}
};
template<typename SIGNAL, typename CONTEXT,typename ...Args>
void connect(SIGNAL* signal, CONTEXT* context, signal_function<CONTEXT, Args...> slot)
{
signal->_slots.push_back(new TanSlot<CONTEXT, Args...>(context, slot));
}
template<typename SIGNAL, typename CONTEXT,typename ...Args>
void disconnect(SIGNAL* signal, CONTEXT* context, signal_function<CONTEXT, Args...> slot)
{
for(auto iter = signal->_slots.begin(); iter != signal->_slots.end(); iter++)
{
TanSlot<CONTEXT, Args...>* p_slot = (TanSlot<CONTEXT, Args...>*)*iter;
if(*p_slot == context && *p_slot == slot)
{
delete p_slot;
signal->_slots.erase(iter);
break;
}
}
}
main.cpp
#include "TanMetaObject.h"
#include <iostream>
class A
{
public:
TanSignal<int, const char*> signal;
void function(int a, const char* str){
printf("function slot:%d, %s\n", a, str);
}
};
class B
{
public:
void function1(int a, const char* str){
printf("class B slot:%d, %s\n", a, str);
}
};
class C
{
public:
void function2(int a, const char* str){
printf("class C slot:%d, %s\n", a, str);
}
};
int main(void)
{
A a; B b; C c;
connect(&a.signal, &a, &A::function);
connect(&a.signal, &b, &B::function1);
connect(&a.signal, &c, &C::function2);
a.signal.emit(111, "123");
printf("**********\n");
disconnect(&a.signal, &c, &C::function2);
a.signal.emit(123, "abc");
return 0;
}