C++ QT:使用移动语义将信号连接到插槽

C++ QT:使用移动语义将信号连接到插槽,c++,qt,c++11,move,qt-signals,C++,Qt,C++11,Move,Qt Signals,好的,我有这样的东西: void EmailReceiverThread::foreachEmailAccount(ConfigEmailAccount account) { Email email; EmailReader emailReader(account); while (emailReader.pollEmail(email)) { writeEmailToDatabase(email); } } ForeachEmailAc

好的,我有这样的东西:

void EmailReceiverThread::foreachEmailAccount(ConfigEmailAccount account)
{
    Email email;
    EmailReader emailReader(account);
    while (emailReader.pollEmail(email))
    {
        writeEmailToDatabase(email);
    }
}
ForeachEmailAccount是EmailReceiverThread中的一个插槽。它是从run()方法调用的:

GetConfigEmailDAO执行查询、获取电子邮件帐户并执行以下操作:

emit emailAccount(account);
到目前为止,这是可行的。问题是,我正在复制ConfigEmailAccount类。我想避免那场表演的打击。因此,我的想法是使用c++11移动语义发送帐户:

emit emailAccount(std::move(account));
我用新语法重写了插槽和信号:

void foreachEmailAccount(ConfigEmailAccount&& account);
不幸的是,这不起作用。我有下一个编译错误:

moc_emailreceiverthread.cpp:88: error: cannot bind ‘ConfigEmailAccount’ lvalue to ‘ConfigEmailAccount&&’
     case 1: _t->foreachEmailAccount((*reinterpret_cast< ConfigEmailAccount(*)>(_a[1]))); break;
moc\u emailreceiverthread.cpp:88:错误:无法将'ConfigEmailAccount'左值绑定到'ConfigEmailAccount&'
案例1:_t->foreachEmailAccount((*重新解释(_a[1]));打破
我能做什么

此处的最小可验证示例:

#include <QCoreApplication>
#include <QObject>

class ConfigEmailAccount
{
    QString some_data;
};

class GetConfigEmailDAO : public QObject
{
    Q_OBJECT
public:
    void execute();

signals:
    void emailAccount(ConfigEmailAccount&& account);
};

void GetConfigEmailDAO::execute()
{
    ConfigEmailAccount account;
    emit emailAccount(std::move(account));
}

class EmailReceiverThread : public QObject
{
    Q_OBJECT
public:
    void execute();
public slots:
    void foreachEmailAccount(ConfigEmailAccount&& account);
};

void EmailReceiverThread::execute()
{

    GetConfigEmailDAO* accountReader = new GetConfigEmailDAO;
    connect(accountReader, SIGNAL(emailAccount(ConfigEmailAccount)),
            this, SLOT(foreachEmailAccount(ConfigEmailAccount)), Qt::QueuedConnection);
    accountReader->execute();
}

void EmailReceiverThread::foreachEmailAccount(ConfigEmailAccount&& account)
{

}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qRegisterMetaType<ConfigEmailAccount>("ConfigEmailAccount");
    EmailReceiverThread reader;
    reader.execute();
    return a.exec();
}

#include "main.moc"
#包括
#包括
类ConfigEmailAccount
{
QString一些_数据;
};
类GetConfigEmailDAO:公共QObject
{
Q_对象
公众:
void execute();
信号:
作废emailAccount(配置emailAccount&&account);
};
void GetConfigEmailDAO::execute()
{
配置电子邮件帐户;
发送emailAccount(std::move(account));
}
类EmailReceiverThread:公共QObject
{
Q_对象
公众:
void execute();
公众时段:
作废foreachEmailAccount(ConfigEmailAccount&&account);
};
作废EmailReceiverThread::execute()
{
GetConfigEmailDAO*accountReader=新建GetConfigEmailDAO;
连接(accountReader,信号(emailAccount(ConfigEmailAccount)),
这个插槽(foreachemailcount(ConfigEmailAccount)),Qt::QueuedConnection);
accountReader->execute();
}
作废EmailReceiverThread::foreachEmailAccount(ConfigEmailAccount&&account)
{
}
int main(int argc,char*argv[])
{
qcorea应用程序(argc、argv);
qRegisterMetaType(“ConfigEmailAccount”);
电子邮件接收线程阅读器;
reader.execute();
返回a.exec();
}
#包括“main.moc”

最后,我采用了QT的浅拷贝机制:

我敢打赌,Qt的信号和插槽中没有对移动语义和右值引用的特殊支持,因为它们是在C++之前11次设计的。因此,您最好使用Qt的本机解决方案来避免大量复制:或者重新设计要使用的
ConfigEmailAccount
类,或者,如果很难或不可能,对信号和插槽使用
QSharedPointer
。您可以简单地通过指针传递对象。为什么不将其包装为
std::shared_ptr
并传递?如果将多个插槽连接到同一信号,会发生什么情况?
#include <QCoreApplication>
#include <QObject>

class ConfigEmailAccount
{
    QString some_data;
};

class GetConfigEmailDAO : public QObject
{
    Q_OBJECT
public:
    void execute();

signals:
    void emailAccount(ConfigEmailAccount&& account);
};

void GetConfigEmailDAO::execute()
{
    ConfigEmailAccount account;
    emit emailAccount(std::move(account));
}

class EmailReceiverThread : public QObject
{
    Q_OBJECT
public:
    void execute();
public slots:
    void foreachEmailAccount(ConfigEmailAccount&& account);
};

void EmailReceiverThread::execute()
{

    GetConfigEmailDAO* accountReader = new GetConfigEmailDAO;
    connect(accountReader, SIGNAL(emailAccount(ConfigEmailAccount)),
            this, SLOT(foreachEmailAccount(ConfigEmailAccount)), Qt::QueuedConnection);
    accountReader->execute();
}

void EmailReceiverThread::foreachEmailAccount(ConfigEmailAccount&& account)
{

}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    qRegisterMetaType<ConfigEmailAccount>("ConfigEmailAccount");
    EmailReceiverThread reader;
    reader.execute();
    return a.exec();
}

#include "main.moc"