4

Ok, i have something like this:

void EmailReceiverThread::foreachEmailAccount(ConfigEmailAccount account)
{
    Email email;
    EmailReader emailReader(account);
    while (emailReader.pollEmail(email))
    {
        writeEmailToDatabase(email);
    }
}

ForeachEmailAccount is a slot in EmailReceiverThread. It's called from the run() method:

GetConfigEmailDAO* accountReader = new GetConfigEmailDAO(type, m_channel);
connect(accountReader, SIGNAL(emailAccount(ConfigEmailAccount)),
        this, SLOT(foreachEmailAccount(ConfigEmailAccount)), Qt::QueuedConnection);
DbThread::postAction(accountReader);

GetConfigEmailDAO does a query, fetch the email account and do the emit:

emit emailAccount(account);

This works so far. The problem is, i'm copying the class ConfigEmailAccount. I would like avoid that perfomance hit. So, my idea is emit the account using c++11 move semantics:

emit emailAccount(std::move(account));

I rewrited the slots and signals with the new syntax:

void foreachEmailAccount(ConfigEmailAccount&& account);

Unfortunaly, this doesn't work. I have the next compilation error:

moc_emailreceiverthread.cpp:88: error: cannot bind ‘ConfigEmailAccount’ lvalue to ‘ConfigEmailAccount&&’
     case 1: _t->foreachEmailAccount((*reinterpret_cast< ConfigEmailAccount(*)>(_a[1]))); break;

What could i do?

Minimal verifiable example here:

#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"
amchacon
  • 1,891
  • 1
  • 18
  • 29
  • I bet there's no special support for move semantics and rvalue references in Qt's signals and slots as they were designed in pre-C++11 times. Thus, you are much better off using Qt's native solution for avoiding heavy copying: either redesign `ConfigEmailAccount` class to use [implicit sharing](https://doc.qt.io/qt-5/implicit-sharing.html) or, if it's hard or impossible, use `QSharedPointer` for signals & slots. – Dmitry Oct 02 '17 at 08:17
  • You might simply pass your objects by pointers. – vahancho Oct 02 '17 at 08:21
  • 1
    Why not just wrap it as `std::shared_ptr` and pass that around? – rustyx Oct 02 '17 at 09:06
  • 2
    What will happen if you connect multiple slots to the same signal? – Velkan Oct 03 '17 at 06:03

1 Answers1

2

Finally, i adopted the shallow copy mechanism of QT:
http://doc.qt.io/qt-5.6/qshareddatapointer.html#details

amchacon
  • 1,891
  • 1
  • 18
  • 29