如何在QT信号和槽中使用模板?

14

我想在我的程序中使用信号和槽,但是不幸的是它们应该用于传输多种不同的数据类型(例如QString,double等),我不想为每种数据类型编写二十个不同的槽。但是当我想声明一个槽时

template <typename t>
void Slot1(t data);

QT告诉我,在信号和槽中无法使用模板。是否有解决方法?或者我的方法可以改进吗?


3
使用QVariant怎么样? - sjdowling
看起来很有趣,但以前从没听说过! - arc_lupus
如果不行,那么std::any呢?我发现QVariant很难使用。 - namezero
2个回答

13

准确的答案:这是不可能的

解决方法:您可以使用新的信号和槽语法来实现类似的功能:

QSlider *slid = new QSlider;
QLineEdit *lne = new QLineEdit;

connect(slid,&QSlider::valueChanged,this,&MainWindow::random);
connect(lne,&QLineEdit::textChanged,this,&MainWindow::random);
lne->show();
slid->show();

插槽:

void MainWindow::random(QVariant var)
{
    qDebug() << var;
}

输出:

QVariant(int, 11) 
QVariant(int, 12) 
QVariant(int, 13) 
QVariant(int, 14) 
QVariant(int, 16) 
QVariant(QString, "c") 
QVariant(QString, "cv") 
QVariant(QString, "cvb") 
QVariant(QString, "cvbc") 
QVariant(QString, "cvbcv")

为什么? http://qt-project.org/wiki/New_Signal_Slot_Syntax

如果存在隐式转换(例如从QString到QVariant),则可以自动转换类型。


2
这完全没有回答问题。:( - Jean-Michaël Celerier
4
@Jean-MichaëlCelerier,比起简单回答“不可能”,我的回答更好。同时,提问者也询问了:“是否有变通方法?或者我的方法能否简单改进?”而我的回答则解释了如何实现类似template的功能。详见:http://chernobyllab.blogspot.com/2015/04/how-to-use-templates-with-qt-signals.html - Jablonski

2
Lambda函数可以解决这个问题。例如,在您的情况下:
class A : public QObject
{
    Q_OBJECT
signals:
    void signal1();
}

class B : public QObject
{
    Q_OBJECT

    template <typename t>
    void Slot1(t data);
}

A* ptra = new A();
B* ptrb = new B();
connect(ptra, &A::signal1, this, [=](){ptrb->Slot1(666);});

它基本上在类中创建了一个无名称的插槽,调用connect函数并使用此插槽来调用模板函数。在这种情况下,模板函数不必是插槽。


1
实际上(在Qt 5.12.8,QMake 3.1上测试过),您可以直接将模板成员函数(已实例化)连接到信号。假设有一个类MyClass,具有模板成员函数template <typename T> print() { qInfo() << typeid( T ).name() << "\n"; },则以下连接是有效的:connect( myButon, &QPushButton::clicked, this, &MyClass::print<int> ) - LRDPRDX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接