LINUX.ORG.RU

[я вылез из криокамеры] Новые сигналы/слоты в Qt5 или «привет, c++11!»


0

2

!Ъ: тык

Ъ:

Старый вариант останется доступен.

Новый вариант разрешается на этапе компиляции (а не исполнения), и работает не со строками.

Было:

connect(sender, SIGNAL(valueChanged(QString,QString)), receiver, SLOT(updateValue(QString)));

Стало:

connect(sender, &Sender::valueChanged, receiver, &Receiver::updateValue );

Можно так:

connect(sender, &Sender::valueChanged, 
    tr1::bind(receiver, &Receiver::updateValue, "senderValue", tr1::placeholder::_1) );

Или так:

connect(sender, &Sender::valueChanged, [=](const QString &newValue) {
        receiver->updateValue("senderValue", newValue);
    });

Можно писать код прямо в коннектах:

void doYourStuff(const QByteArray &page)
{
    QTcpSocket *socket = new QTcpSocket;
    socket->connectToHost("qt.nokia.com", 80);
    QObject::connect(socket, &QTcpSocket::connected, [socket, page] () {
        socket->write(QByteArray("GET " + page + "\r\n"));
    });
    QObject::connect(socket, &QTcpSocket::readyRead, [socket] () {
        qDebug()<< "GOT DATA "<< socket->readAll();
    });
    QObject::connect(socket, &QTcpSocket::disconnected, [socket] () {
        qDebug()<< "DISCONNECTED ";
        socket->deleteLater();
    });
 
    QObject::connect(socket, static_cast<void (QTcpSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error), [socket] (QAbstractSocket::SocketError) {
        qDebug()<< "ERROR " << socket->errorString();
        socket->deleteLater();
    });
}

★★★★★

Последнее исправление: ChALkeR (всего исправлений: 3)

Ответ на: комментарий от EtherealPhantom

но когда они исполняются, в какой момент времени

Как и всё в С++, результатом лямбда выражения является функциональный объект, а по сигналу к объекту применяется оператор ().

Вызов обычной именованной функции, объявленной в той же области видимости перед выражением

Когда в C++ появлись вложенные функции? Если не считать их имитацию на лябмдах.

По логике самого connect()-а должно выполняться взятие адреса лямбды.

По логике реализации лямбд - копирование или перемещение.

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

>Как и всё в С++, результатом лямбда выражения является функциональный объект, а по сигналу к объекту применяется оператор ().

Почему именно по сигналу, а не перед вызовом connect() ?

EtherealPhantom
()
Ответ на: комментарий от EtherealPhantom

> Почему именно по сигналу, а не перед вызовом connect() ?

Потому что тебе нужно исполнять слот («к объекту применяется оператор ()») по сигналу, а не по коннекту?

anonymous
()

но ведь и первоначальный вариант тоже на этапе компиляции после MOC-а, или не? я ошибаюсь? в любом случае, приветствую, а вот это «Можно писать код прямо в коннектах» - это супермегаулёт и круто

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от anonymous

>>Почему именно по сигналу, а не перед вызовом connect() ?

Потому что тебе нужно исполнять слот («к объекту применяется оператор ()») по сигналу, а не по коннекту?


Это тот же самый обычный connect() или его специальная перегруженная версия?

Откуда connect() знает, что к функтору не нужно применять оператор () сразу для вычисления значения аргумента (адреса слота), а нужно просто скопировать этот объект к себе в потроха, чтобы потом применить к нему () по сигналу?

EtherealPhantom
()
Ответ на: комментарий от I-Love-Microsoft

это супермегаулёт и круто

А gtkmm с Boost.Lambda и сейчас позволяет так делать :-)

Begemoth ★★★★★
()
Ответ на: комментарий от EtherealPhantom

Это тот же самый обычный connect() или его специальная перегруженная версия?

Как ты в старый коннект

bool QObject::connect(QObject* sender, const char* signal, QObject* receiver, const char* method, Qt::ConnectionType type)

передашь функциональный объект? Конечно это новая функция, перегружающая имя connect.

Откуда connect() знает, что к функтору не нужно применять оператор () сразу для вычисления значения аргумента (адреса слота), а нужно просто скопировать этот объект к себе в потроха, чтобы потом применить к нему () по сигналу?

Оттуда же, откуда и алгоритмы стандартной библиотеки, потому что это знают программисты их написавшие :-)

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

Конечно это новая функция, перегружающая имя connect.

Поправка: это шаблон функции, а не функция.

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

>Как ты в старый коннект передашь функциональный объект?

Компиляторной магией. По началу я было подумал что это просто какая-то хитрая новая оптимизация, позволяющая не то отдавать лямбды вместо обычных функций, не то по-новому инлайнить код с их помощью.

Конечно это новая функция, перегружающая имя connect.


Это многое объясняет :)

EtherealPhantom
()
Ответ на: комментарий от I-Love-Microsoft

Слоты традиционно принадлежат объектам и реализуются обычно в том же модуле, где и весь остальной код объекта. Теперь получается можно раскидать код слотовых объектов по коннектам, которые вообще могут где угодно находиться. Круто конечно, но подход несколько сомнительный, т.к. такой стиль может легко привести к запутыванию кода.

EtherealPhantom
()
Ответ на: комментарий от EtherealPhantom

Теперь получается можно раскидать код слотовых объектов по коннектам, которые вообще могут где угодно находиться.

Как будто сейчас не так. Сигналы и слоты в частности используются для связи независимых модулей программы.

Begemoth ★★★★★
()
Ответ на: комментарий от fat_angel

Справедливости ради стоит отметить, что GObject еще большая жесть.

Вот только не надо такие какашки вспоминать :)

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от otto

Например, не работает с шаблонами классов и функций, игнорирует препроцессор C.

Begemoth ★★★★★
()
Ответ на: комментарий от Eddy_Em

>Вот только не надо такие какашки вспоминать :)

Т.е. ты пишешь на GTK+, но при этом стараешься держаться подальше от GObject'а? Ты как всегда в своем репертуаре!

fat_angel ★★★★★
()
Ответ на: комментарий от rival

>I’ll present some opinions for a potential new build system

Так что видимо нет. Не помню кто писал… впрочем, вряд ли до того же Qt 6 что поменяется.

Deleted
()
Ответ на: комментарий от Eddy_Em

>Зачем мне эти монструозные конструкции?

Как захочешь запилить какой-нибудь хитро вывернутый виджет, узнаешь…

fat_angel ★★★★★
()
Ответ на: комментарий от fat_angel

Не захочу. Гарантирую (мне хватает стандартных виджетов). И вообще, GUI - зло, там должно быть минимум элементов.

Eddy_Em ☆☆☆☆☆
()

Собственно даже на C++98 вполне возможно было реализовать нечто подобное. Разве что пришлось бы ограничиться неким максимальным количеством аргументов для сигналов/слотов в виду отстуствия в C++98 variadic templates. Как по мне, так «новый» синтаксис гораздо понянтее, плюс внутри оно должно работать НЕ методом сравнения сигнатур функций в СТРОКОВОМ представлении, что гораздо быстрее.

m0rph ★★★★★
()
Ответ на: комментарий от Begemoth

> Нет, на то, что Qt на 15 лет отстаёт от Tcl/Tk.

Тогда как-то не очень корректно сравнивать Tcl с C++.

anonymous
()
Ответ на: комментарий от otto

> А чем moc так плох?

Вводит новые сущности в синтаксис, из-за которых отказаться от него сильно проблематично. Не знает обычный плюсовый компилятор слова emit, и не будет знать. Кроме того, этот emit невозможно применять в RAII (у меня не получилось), а зачастую очень надо. Ну и ещё всякие мелочи, так сразу всё и не припомню.

one_more_hokum ★★★
()
Ответ на: комментарий от one_more_hokum

Вводит новые сущности в синтаксис, из-за которых отказаться от него сильно проблематично.

Нет, он просто генерирует вспомогательный код.

Не знает обычный плюсовый компилятор слова emit

Это просто

#define emit

Кроме того, этот emit невозможно применять в RAII

А пример можно?

Begemoth ★★★★★
()
Ответ на: комментарий от one_more_hokum

> Не знает обычный one_more_hokum слова emit, и не будет знать.

Так, к слову, emit и moc никак не связаны.

anonymous
()
Ответ на: комментарий от anonymous

emit и moc никак не связаны

Болеете? Вот специально сейчас погрепал исходники Qt — есть только #define emit, но этот макрос никак не раскрывается. И в интернетах тоже пишут, что emit и прочие SIGNALS/SLOTS являются ключевыми словами moc-а.

one_more_hokum ★★★
()
Ответ на: комментарий от one_more_hokum

Документация может ошибаться. Погрепай исходники moc'а и убедись, что он никак не использует emit define. Если этого будет мало, то убери emit'ы из рандомной программы и сравни получившийся бинарник с тем, в котором есть emit'ы.

anonymous
()
Ответ на: комментарий от one_more_hokum

Вот специально сейчас погрепал исходники Qt — есть только #define emit, но этот макрос никак не раскрывается.

А зачем ему раскрываться во что-то отличное от пустой последовательности лексем?

Begemoth ★★★★★
()
Ответ на: комментарий от anonymous
//qt/src/corelib/kernel/qobjectdefs.h
#ifndef Q_MOC_RUN
# if defined(QT_NO_KEYWORDS)
#  define QT_NO_EMIT
# else
#   define slots
#   define signals protected
# endif
# define Q_SLOTS
# define Q_SIGNALS protected
# define Q_PRIVATE_SLOT(d, signature)
# define Q_EMIT
#ifndef QT_NO_EMIT
# define emit
#endif

Никак не связано с moc, да...

one_more_hokum ★★★
()
Ответ на: комментарий от one_more_hokum

Никак не связано с moc, да...

Ты что думаешь, что moc как-то изменяет твои исходники? Ты попробуй скомпилировать программу не вызывая moc, единственное, что ты получишь - это ошибки компоновки, как раз те вспомогательные функции, которые генерирует moc, а выдача сигнала скомпилируется просто в вызов одноимённой функции.

Begemoth ★★★★★
()
Ответ на: комментарий от Begemoth

> moc как-то изменяет твои исходники?

Moc генерирует дополнительные файлы, в которых и делает всю свою унутреннюю препроцессорную магию.

one_more_hokum ★★★
()
Ответ на: комментарий от one_more_hokum

> Q_MOC_RUN, я так понимаю, ускользнул от твоего пытливого взора?

Что ты пытаешься мне доказать, что emit является кейвордом moc'а? Формально может и является, но moc его никак не использует, совершенно.
Этот кейворд пустышка. Почему тебе так сложно признать это?

anonymous
()
Ответ на: комментарий от anonymous

> ты пытаешься мне доказать, что emit является кейвордом moc'а?

Не только он, а ещё довольно много прочих, в том числе SIGNALS и SLOTS.

one_more_hokum ★★★
()
Ответ на: комментарий от one_more_hokum

> Не только он, а ещё довольно много прочих, в том числе SIGNALS и SLOTS.

Я думал, речь шла про emit.
Ладно, неважно. У меня сложилось впечатление, что ты понятия не имеешь как и что делает moc, но у тебя все равно какой-то иррациональный «страх» всей этой магии.
Не читал, но осуждаю. (с)

anonymous
()
Ответ на: комментарий от Begemoth

Я говорил о Tk как о тулките. Естественно, пользоваться им не доводилось, и соответственно изнутри его не знаю. Может это вы мне объясните, что там такого совершенного, что одна только обработка событий отбрасывает Qt на 15 лет? Оно что, мысли умеет читать, и само может догадаться что делать при событии?

son_of_a_gun
()
Ответ на: комментарий от webhamster

Нормальный код она породила.

Deleted
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.