In the end, I used this way to achieve it. I cant to write a template that can accommodate any number of parameters.
template <typename T>
struct lambda_traits : lambda_traits<decltype(&T::operator())> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct lambda_traits<ReturnType(ClassType::*)(Args...) const>
{
static const std::size_t arity = sizeof...(Args);
using Tuple = std::tuple<Args...>;
};
class Debounced
{
public:
template <typename Func1, typename Func2>
static inline typename std::enable_if<lambda_traits<Func2>::arity == 0, QMetaObject::Connection>::type
connect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, Func1 signal, const QObject* context, Func2 slot,
Qt::ConnectionType type = Qt::AutoConnection)
{
QTimer* timer = new QTimer((QObject*)context);
timer->setSingleShot(true);
QObject::connect(sender, signal, timer, [=]() { timer->start(200); });
return QObject::connect(timer, &QTimer::timeout, context, std::move(slot), type);
}
template <typename Func1, typename Func2>
static inline typename std::enable_if<lambda_traits<Func2>::arity == 1, QMetaObject::Connection>::type
connect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, Func1 signal, const QObject* context, Func2 slot,
Qt::ConnectionType type = Qt::AutoConnection)
{
QTimer* timer = new QTimer((QObject*)context);
timer->setSingleShot(true);
using ParamType0 = std::tuple_element<0, lambda_traits<Func2>::Tuple>::type;
ParamType0* p0 = new ParamType0;
QObject::connect(sender, signal, timer, [=](ParamType0 p) {*p0 = p; timer->start(200); });
return QObject::connect(timer, &QTimer::timeout, context, [=]() {slot(*p0); }, type);
}
};
#include <QApplication>
#include <QTimer>
#include <QSlider>
#include <QDoubleSpinBox>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
auto w = new QWidget();
auto sl = new QSlider(w);
auto dsp = new QDoubleSpinBox(w);
w->show();
sl->move(10,30);
w->resize(50, 200);
Debounced::connect(sl, &QSlider::valueChanged, sl, []() {printf("222 "); });
Debounced::connect(sl, &QSlider::valueChanged, sl, [](int v) {printf("%d ", v); });
Debounced::connect(dsp, QOverload<double>::of(&QDoubleSpinBox::valueChanged), dsp, [](double v) {printf("%f ", v); });
return app.exec();
}