Умный указатель сигнал-слот

64
14 апреля 2021, 22:40

Попробовал передать умный указатель std::unique_ptr через сигнал/слот и получил ошибку из за удаленного конструктора копирования (unique_ptr(const unique_ptr&) = delete;). Так можно ли использовать умный указатель std::unique_ptr в сигнал/стол? UDP: нельзя! Связный вопрос: Как передавать большие контейнеры между потоками?

Переделал класс под указатель std::shared_ptr<Data>. Используя замечания @yrHeTaTeJlb, вызываю: Q_DECLARE_METATYPE(std::shared_ptr<Data>); и qRegisterMetaType<std::shared_ptr<Data>>("shared_ptr<Data>");. И все заработало.

Вывод qDebug():

Data();
finish
~Data();

mainwwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMap>
#include <memory>
class Data {
    QMap<int, QString> _m;  // большие
    std::array<QString, 1024*1024> _a;
public:
    Data() { qDebug() << "Data();"; }
    ~Data() { qDebug() << "~Data();"; }
    void initData();
};
Q_DECLARE_METATYPE(std::shared_ptr<Data>);
class Worker : public QObject {
    Q_OBJECT
    std::shared_ptr<Data> _d;
public:
    Worker() : QObject(), _d(std::make_shared<Data>()) { }
signals:
    void finished(std::shared_ptr<Data> d);
public slots:
    void process() { _d->initData(); emit finished(_d); }
};
class Controller : public QObject {
    Q_OBJECT
    std::shared_ptr<Data> _d;
public:
    Controller(QObject *parent = nullptr) : QObject(parent) { }
    void start();
signals:
    void finished(std::shared_ptr<Data> d);
};
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private:
    Ui::MainWindow *ui;
    Controller _c;
    std::shared_ptr<Data> _d;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QStandardItemModel>
#include <QThread>
void Data::initData() { /*some init code*/ }
void Controller::start() {
    QThread *thr = new QThread;
    Worker *w = new Worker;
    w->moveToThread(thr);
    connect(thr, &QThread::started, w, &Worker::process);
    connect(w, &Worker::finished, this, &Controller::finished);
    connect(w, &Worker::finished, thr, &QThread::quit);
    connect(w, &Worker::finished, w, &Worker::deleteLater);
    connect(thr, &QThread::finished, thr, &QThread::deleteLater);
    thr->start();
}
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent), ui(new Ui::MainWindow) {
    qRegisterMetaType<std::shared_ptr<Data>>("shared_ptr<Data>");
    ui->setupUi(this);
    connect(&_c, &Controller::finished, this, [this] (std::shared_ptr<Data> d) { qDebug() << "finish"; _d = d; });
    _c.start();
}
MainWindow::~MainWindow() { delete ui; }
Answer 1

По умолчанию connect выполянется с Qt::AutoConnection.

Если сигнал передается между потоками Qt::AutoConnection == Qt::QueuedConnection

Для того чтобы передавать объекты c Qt::QueuedConnection их тип нужно зарегистрировать через QMetaType::qRegisterMetaType.

Для этого тип нужно сначала объявить через Q_DECLARE_METATYPE.

Q_DECLARE_METATYPE требует чтобы у класса был конструктор копирования, а у std::unique_ptr его нет.

Таким образом передать std::unique_ptr через сигнал из потока в поток не получится.

READ ALSO
Проблема с c++ getline() в gcc

Проблема с c++ getline() в gcc

Потребовалось написать пару простеньких скриптов на c++До этого когда-то писал в Visual Studio, сейчас сижу на linux(fedora 29), поэтому перешёл на gcc

80
arborjs в angular, как подключить библиотеку?

arborjs в angular, как подключить библиотеку?

Я использую библиотеку arborjs для построения графов (Я не смог найти установку через npm), как я могу использовать эту библиотеку у себя в проекте?

117
Проблемма с include

Проблемма с include

Я делаю рандом 3 статей из базы данных и добавить их в шаблон и данные из этого шаблона передать в другой шаблон с помощью include (короче: есть...

87