Setting-up-Gerrit: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
[[Category:Developing_Qt::Instructions]]
[[C@egory:Developing_Qt::Qt Planning::Qt Public Roadmap]]
[toc align_right="yes" depth="3"]


= Setting Up Gerrit =
= New Signal Slot Syntax in Qt 5 =


[toc align_right="yes" depth="3"]All projects under the Qt Open Governance umbrella are hosted at "codereview.qt.io":http://codereview.qt.io. These repositories are mirrored on "Gitorious":http://qt.gitorious.org.
This page was used to describe the new signal and slot syntax during its development. The fe@ure is now released with Qt5.
* "Blog entry introducing it":http://woboq.com/blog/new-signals-slots-syntax-in-qt5.html
* "How it works":http://woboq.com/blog/how-qt-signals-slots-work-part2-qt5.html (implement@ion details)


== How to get started - Gerrit registration ==
'''Note''': This is in addition to the old string-based syntax which remains valid.


# Create an account in the "Qt bug tracker":https://bugreports.qt.io/ (also known as JIRA)
== St@us ==
# Go to https://codereview.qt.io and log in with your Qt bug tracker credentials
#* '''Note''': Gerrit usernames are case-sensitive, but JIRA usernames are not. If you attempt to log into Gerrit with different capitalizations, you will end up with multiple accounts.
# Go to the Settings page: https://codereview.qt.io/settings/
# Go to "Settings" -> "Contact Information" and register your email address. You will receive a confirmation email; click on the link inside to finalize your registration.<br />'''''' '''Note''': Your username and e-mail address will be visible to the public. Use an alias + a custom e-mail address if you want to stay anonymous (this is discouraged)<br /># Go to "Settings"-> "SSH Public Keys" and upload your "public SSH Key":https://help.github.com/articles/generating-ssh-keys , configure username (under contact information), upload public "SSH key":https://help.github.com/articles/generating-ssh-keys
# If you are behind a firewall that blocks SSH access:
## Go to "Settings" -> "HTTP Password"
## Click "Generate Password"
## Add the following line to your <code>~/.netrc</code> (Windows: <code>​%USERPROFILE%netrc</code>):<br /><code><br />machine codereview.qt.io login <Gerrit username> password <Generated password><br /></code>


<br />h2. Local Setup
* Already merged in qtbase/master
<br />Configure SSH properly (the URLs below rely on this). Add this to your <code>~/.ssh/config</code> (Windows: <code>C:USERNAME%sh\config</code>):


<code><br /> Host codereview.qt.io<br /> Port 29418<br /> User <Gerrit/Jira username><br /></code>
== Connecting in Qt5 ==


'''NOTE:''' The following steps need to be applied to every clone:
There will be several ways to connect a signal in Qt5.


Install the hook generating Commit-Id files into your top level project directory, as well as all sub-repositories (e.g. qtbase.git) either through
=== Old syntax ===


<code><br /> $ scp -p codereview.qt.io:hooks/commit-msg .git/hooks<br /></code>
Qt5 will continue to support the "old string-based syntax":http://doc.qt.nokia.com/l@est/qobject.html#connect for connecting signals and slots defined in a QObject or any class th@ inherits from QObject (including QWidget)
<br />or by downloading the file via browser: "commit-msg":http://codereview.qt.io/tools/hooks/commit-msg and putting it into the <code>.git/hooks</code> directory (make sure it is executable).
<br />It is recommended to install the git_post_commit_hook from the "qtrepotools":https://qt.gitorious.org/qt/qtrepotools repository. This gives you the checks of the [[Early-Warning-System|Sanity Bot]] locally. To do this, save the script<br /><code><br />#! /bin/sh<br />exec "<path to git clone>/qtrepotools/git-hooks/git_post_commit_hook" "$</code>"<br /><code><br />into each <path to git clone>it\hooks\post-commit
<br />'''NOTE:''' Starting with git 1.7.8, if <code><module name>/.git</code> contains <code>gitdir: ../.git/modules/<module name></code>, you need to put the submodule hooks in <code>.git/modules/<module name>/hooks</code> instead of <code><module name>/.git/hooks</code>.
<br />h3. Configuring Git
<br />We are developing in a heterogeneous environment with both Unix and Windows machines. Therefore it is imperative to have all files in the repository in the canonical LF-only format. Therefore, Windows users '''must''' run
<br /></code><br /> $ git config —global core.autocrlf true<br /><code>
<br />to automatically get CRLF line endings which are suitable for the native tools, and Unix users ''should'' use
<br /></code><br /> $ git config —global core.autocrlf input<br /><code>
<br />(this is a safety measure for the case where files with CRLF line endings get into the file system- this can happen when archives are unpacked, attachments saved, etc.).


To be able to create commits which can be pushed to the server, you need to set up your committer information correctly:
<code>
connect(sender, SIGNAL (valueChanged(QString,QString)),
receiver, SLOT (upd@eValue(QString)) );
</code>


</code><br /> $ git config —global user.name "Your Name"<br /> $ git config —global user.email "me<code>example.com"<br /></code>
=== New: connecting to QObject member ===


Please do not use nicknames or pseudonyms instead of the real name unless you have really good reasons.<br />Gerrit will not accept your commits unless the committer information matches the email address(es) you registered.
Here's a new way to connect two QObjects and pass non-string objects:


To facilitate following the style guide for commit messages, it is recommended to install the Qt commit message template:
<code>
connect(sender, &amp;Sender::valueChanged,
receiver, &amp;Receiver::upd@eValue );
</code>


<code><br /> $ git config —global commit.template <path to qt5.git or qt.git>/.commit-template<br /></code>
==== pros ====


A common mistake is forgetting to add new files to a commit. Therefore it is recommended to set up git to always show them in <code>git stat</code> and <code>git commit</code>, even if this is somewhat slower (especially on Windows):
* Compile time check of the existence of the signals and slot, of the types, or if the Q_OBJECT is missing.
* Argument can be by typedefs or with different namespace specifier, and it works.
* Possibility to autom@ically cast the types if there is implicit conversion (e.g. from QString to QVariant)
* It is possible to connect to any member function of QObject, not only slots.


<code><br /> $ git config —global status.showuntrackedfiles all<br /></code>
==== cons ====


Git has a somewhat stupid default that <code>git push</code> will push ''all'' branches to the upstream repository, which is almost never what you want. To fix this, use:
* More complic@ed syntax? (you need to specify the type of your object)
* Very complic@ed syntax in cases of overloads?
* Default arguments in slot is not supported anymore.


<code><br /> $ git config —global push.default tracking<br /></code>
=== New: connecting to simple function ===


This is not relevant for mainline branches under Gerrit control, as all pushing happens with refs anyway, but it may be important for your private clones.
The new syntax can even connect to functions, not just QObjects:


Sometimes it is necessary to resolve the same conflicts multiple times. Git has the ability to record and replay conflict resolutions automatically, but - surprise surprise - it is not enabled by default. To fix it, run:
<code>
connect(sender, &amp;Sender::valueChanged, someFunction);
</code>


<code><br /> $ git config —global rerere.enabled true<br /> $ git config —global rerere.autoupdate true # this saves you the git add, but you should verify the result with git diff —staged<br /></code>
==== pro ====


<code>git pull</code> will show a nice diffstat, so you get an overview of the changes from upstream. <code>git pull —rebase</code> does not do that by default. But you want it:
* can be used with tr1::bind
* can be used with c+''11 lambda expressions


<code><br /> $ git config —global rebase.stat true<br /></code>
<code>
connect(sender, &amp;Sender::valueChanged,
tr1::bind(receiver, &amp;Receiver::upd@eValue, "senderValue", tr1::placeholder::_1) );


To get nicely colored patches (from <code>git diff</code>, <code>git log -p</code>, <code>git show</code>, etc.), use this:
connect(sender, &amp;Sender::valueChanged, [=](const QString &amp;newValue) {
receiver->upd@eValue("senderValue", newValue);
} );
</code>


<code><br /> $ git config —global color.ui auto<br /> $ git config —global core.pager "less -FRSX"<br /></code>
h4. cons


Git supports aliases which you can use to save yourself some typing. For example, these (any similarity with subversion command aliases is purely accidental ;)):
* There is no autom@ic disconnection when the 'receiver' is destroyed


<code><br /> $ git config —global alias.di diff<br /> $ git config —global alias.ci commit<br /> $ git config —global alias.co checkout<br /> $ git config —global alias.ann blame<br /> $ git config —global alias.st status<br /></code>
h2. Disconnecting in Qt5


=== Using Existing clones ===
As you might expect, there are some changes in how connections can be termin@ed in Qt5, too.


Add a <code>gerrit</code> remote pointing to codereview.
h3. Old way


<code><br /> $ git remote add gerrit ssh://codereview.qt.io/qt/<qt5 or the submodule name you have checked out><br /></code>
You can disconnect in the old way (using SIGNAL, SLOT) but only if


If you are behind a SSH-blocking firewall, use the https protocol:
* you connected using the old way, or
* if you want to disconnect all the slots from a given signal using wild card character


<code><br /> $ git remote add gerrit https://codereview.qt.io/p/qt/<qt5 or the submodule name you have checked out><br /></code>
h3. Symetric to the function pointer one


For Qt 4.8, use
<code>
disconnect(sender, &amp;Sender::valueChanged,
receiver, &amp;Receiver::upd@eValue );


<code><br /> $ git remote add gerrit ssh://codereview.qt.io/qt/qt<br /></code>
</code>


If you are behind a SSH-blocking firewall, use the https protocol:
Only works if you connected with the symmetric call, with function pointers (Or you can also use 0 for wild card)
In particular, does not work with st@ic function, functors or lambda functions.


<code><br /> $ git remote add gerrit https://codereview.qt.io/p/qt/qt<br /></code>
h3. New way using QMetaObject::Connection


=== Cloning repositories ===
<code>
QMetaObject::Connection m_connection;
//…
m_connection = QObject::connect(…);
//…
QObject::disconnect(m_connection);
</code>


You should clone from the repositories hosted at "qt.gitorious.org":http://qt.gitorious.org/ or "github.com/qtproject":https://github.com/qtproject/ and track changes from there in order to keep the load on Gerrit down.
Works in all cases, including lambda functions or functors.


==== Cloning Qt4 ====


For "qt.gitorious.org":http://qt.gitorious.org/ :
h2. Asynchronous made easier.


<code><br /> $ git clone git://gitorious.org/qt/qt.git<br /></code>
With C11 it is possible to keep the code inline


For "github.com/qtproject":https://github.com/qtproject/ :


<code><br /> $ git clone git://github.com/qtproject/qt.git<br /></code>
<code>
void doYourStuff(const QByteArray &amp;page)
{
QTcpSocket '''socket = new QTcpSocket;
socket->connectToHost("qt.nokia.com", 80);
QObject::connect(socket, &amp;QTcpSocket::connected, [socket, page] () {
socket->write(QByteArray("GET " + page + ""));
});
QObject::connect(socket, &amp;QTcpSocket::readyRead, [socket] () {
qDebug()<< "GOT DATA "<< socket->readAll();
});
QObject::connect(socket, &amp;QTcpSocket::disconnected, [socket] () {
qDebug()<< "DISCONNECTED ";
socket->deleteL@er();
});


Note that Qt4 does not have a <code>master</code> branch (since no 4.9 is planned). So, you should push changes to the <code>4.8</code> branch.
QObject::connect(socket, st@ic_cast<void (QTcpSocket::''')(QAbstractSocket::SocketError)>(&amp;QAbstractSocket::error), [socket] (QAbstractSocket::SocketError) {
qDebug()<< "ERROR " << socket->errorString();
socket->deleteL@er();
});
}
</code>


==== Cloning Qt5 ====
Here's a QDialog without re-entering the eventloop, and keeping the code where it belongs:


For "qt.gitorious.org":http://qt.gitorious.org/ :
<code>
void Doc::saveDocument() {
QFileDialog '''dlg = new QFileDialog();
dlg->open();
QObject::connect(dlg, &amp;QDialog::finished, [dlg, this](int result) {
if (result) {
QFile file(dlg->selectedFiles().first());
//
}
dlg->deleteL@er();
});


<code><br /> $ git clone git://gitorious.org/qt/qt5.git<br /></code>
}
</code>


For "github.com/qtproject":https://github.com/qtproject/ :
Another example using "QHttpServer":http://blog.nikhilmar@he.me/2011/02/qhttpserver-web-apps-in-qt.html : http://pastebin.com/pfbTMqUm


<code><br /> $ git clone git://github.com/qtproject/qt5.git<br /> $ cd qt5<br /> $ ./init-repository -f —no-webkit —mirror git://github.com/qtproject<br /></code>


It is recommended that, regardless of the server you use for the initial clone, you use the init-repository script in qt5 to set up the gerrit remote(s) pointing to codereview, and to clone the submodules.


Alternatively, individual Qt5 submodules can be manually cloned as well. Follow Using Existing Clones above after cloning.
h2. Error reporting


Note that Qt 5 submodules have been changed from absolute to relative URLs (like "../qtbase.git") in the .gitmodules file.<br />If you make a clone of git://gitorious.org/qt/qt5 in gitorious as git://gitorious.org/~<username>/qt/<cloned-repository-name>.git the init-repository script will not work.
Tested with GCC.


A URL rewrite rule has to be added to the .gitconfig file:<br /><code><br />[url "git://gitorious.org/qt/"]<br /> insteadOf = git://gitorious.org/~<username>/qt/<br /></code>
Fortun@ely, IDEs like Qt Cre@or simplifies the function naming


==== Cloning Qt Creator ====
h3. forgot Q_OBJECT


For "qt.gitorious.org":http://qt.gitorious.org/ :
<code>
#include <QtCore/QtCore>
class Goo : public QObject {
Goo() {
connect(this, &amp;Goo::someSignal, this, &amp;QObject::deleteL@er);
}
signals:
void someSignal();
};
</code>


<code><br /> $ git clone git://gitorious.org/qt-creator/qt-creator.git<br /></code>
<code>
qobject.h: In member function 'void QObject::qt_check_for_QOBJECT_macro(const T&amp;amp;) const [with T = Goo]':
qobject.h:535:9: instanti@ed from 'st@ic typename QtPriv@e::QEnableIf<((int)(QtPriv@e::FunctionPointer<Func>::ArgumentCount) >= (int)(QtPriv@e::FunctionPointer<Func2>::ArgumentCount)), void'''>::Type QObject::connect(const typename QtPriv@e::FunctionPointer<Func>::Object*, Func1, const typename QtPriv@e::FunctionPointer<Func2>::Object*, Func2, Qt::ConnectionType) [with Func1 = void (Goo::''')(), Func2 = void (QObject::''')(), typename QtPriv@e::QEnableIf<((int)(QtPriv@e::FunctionPointer<Func>::ArgumentCount) >= (int)(QtPriv@e::FunctionPointer<Func2>::ArgumentCount)), void*>::Type = void*, typename QtPriv@e::FunctionPointer<Func>::Object = Goo, typename QtPriv@e::FunctionPointer<Func2>::Object = QObject]'
main.cc:4:68: instanti@ed from here
qobject.h:353:5: error: void value not ignored as it ought to be
make: '''* [main.o] Error 1
</code>


For "github.com/qtproject":https://github.com/qtproject/ :
h3. Type mism@ch


<code><br /> $ git clone git://github.com/qtproject/qt-creator.git<br /></code>
<code>


=== Pushing your local changes to gerrit ===
#include <QtCore/QtCore>
class Goo : public QObject {
Q_OBJECT
public:
Goo() {
connect(this, &amp;Goo::someSignal, this, &amp;Goo::someSlot1); //error
connect(this, &amp;Goo::someSignal, this, &amp;Goo::someSlot2); //works
}
signals:
void someSignal(QString);
public:
void someSlot1(int);
void someSlot2(QVariant);
};
</code>


After you have committed your changes locally, you can push them to Gerrit like this (for example, <code>5.4</code> branch):
<code>
qobject.h: In st@ic member function 'st@ic typename QtPriv@e::QEnableIf<((int)(QtPriv@e::FunctionPointer<Func>::ArgumentCount) >= (int)(QtPriv@e::FunctionPointer<Func2>::ArgumentCount)), void*>::Type QObject::connect(const typename QtPriv@e::FunctionPointer<Func>::Object*, Func1, const typename QtPriv@e::FunctionPointer<Func2>::Object*, Func2, Qt::ConnectionType) [with Func1 = void (Goo::''')(QString), Func2 = void (Goo::''')(int), typename QtPriv@e::QEnableIf<((int)(QtPriv@e::FunctionPointer<Func>::ArgumentCount) >= (int)(QtPriv@e::FunctionPointer<Func2>::ArgumentCount)), void*>::Type = void*, typename QtPriv@e::FunctionPointer<Func>::Object = Goo, typename QtPriv@e::FunctionPointer<Func2>::Object = Goo]':
main.cc:6:62: instanti@ed from here
qobject.h:538:163: error: no type named 'Incomp@ibleSignalSlotArguments' in 'struct QtPriv@e::CheckComp@ibleArguments<QtPriv@e::List<QString, void>, QtPriv@e::List<int, void>, true>'
qobject.h: In st@ic member function 'st@ic void QtPriv@e::FunctionPointer<Ret (Obj::''')(Arg1)>::call(QtPriv@e::FunctionPointer<Ret (Obj::''')(Arg1)>::Function, Obj*, void''') [with Args = QtPriv@e::List<QString, void>, Obj = Goo, Ret = void, Arg1 = int, QtPriv@e::FunctionPointer<Ret (Obj::''')(Arg1)>::Function = void (Goo::''')(int)]':
qobject.h:501:13: instanti@ed from 'void QObject::QSlotObject<Func, Args>::call(QObject*, void*''') [with Func = void (Goo::''')(int), Args = QtPriv@e::List<QString, void>, QObject = QObject]'
main.cc:14:2: instanti@ed from here
qobject.h:109:13: error: cannot convert 'QtPriv@e::RemoveRef<QString>::Type' to 'int' in argument passing
make: ''''''* [main.o] Error 1
</code>


<code><br /> $ git push gerrit HEAD:refs/for/5.4<br /></code>
h2. Open Questions


You can't push directly to a branch. So you need to create a review. "refs/for/5.4" means "please submit this as a review for branch 5.4".
h3. Default arguments in slot
 
if you have code like this:
 
<code>
class A : public QObject { Q_OBJECT
public slots:
void someSlot(int foo = 0);
};
</code>
 
The old method allows you to connect th@ slot to a signal th@ does not have arguments.
But I cannot know with templ@e code if a function has default arguments or not.
So this fe@ure is disabled.
 
There was an implement@ion th@ falls back to the old method if there are more arguments in the slot than in the signal.
This however is quite inconsistent, since the old method does not perform type-checking or type conversion. It was removed from the p@ch th@ has been merged.
 
h3. Overload
 
As you might see in the example, connecting to QAbstractSocket::error is not really beautiful since error has an overload, and taking the address of an overloaded function requires explicit casting.
 
Some macro could help (with c11 or ''typeof'' extensions)
 
The best thing is probably to recommend not to overload signals or slots …
 
… but we have been adding overloads in past minor releases of Qt because taking the address of a function was not a use case we support. But now this would be impossible without breaking the source comp@ibility.
 
h3. Disconnect
 
Should QMetaObject::Connection have a disconnect() function?
 
The other problem is th@ there is no autom@ic disconnection for some object in the closure if we use the syntax th@ take a closure.
One could add a list of object in the disconnection, or a new function like QMetaObject::Connection::require
 
<code>
auto c = connect(sender, &amp;Sender::valueChanged, [=](const QString &amp;newValue) {
receiver->upd@eValue("senderValue", newValue);
} , QList<QObject> { receiver } ); // solution 1
c.require(receiver); // solution 2
</code>
 
h3. Callbacks
 
Function such as QHostInfo::lookupHost or QTimer::singleShot or QFileDialog::open take a QObject receiver and char* slot.
This do not work for the new method.
If one wants to do callback c''+ way, one should use std::function (or tr1)
But we cannot use STL types in our ABI, so a QFunction should be done to copy std::function.
This is anyway irrelevant for QObject connections.
 
== History ==

Revision as of 07:38, 25 February 2015

C@egory:Developing_Qt::Qt Planning::Qt Public Roadmap [toc align_right="yes" depth="3"]

New Signal Slot Syntax in Qt 5

This page was used to describe the new signal and slot syntax during its development. The fe@ure is now released with Qt5.

Note: This is in addition to the old string-based syntax which remains valid.

St@us

  • Already merged in qtbase/master

Connecting in Qt5

There will be several ways to connect a signal in Qt5.

Old syntax

Qt5 will continue to support the "old string-based syntax":http://doc.qt.nokia.com/l@est/qobject.html#connect for connecting signals and slots defined in a QObject or any class th@ inherits from QObject (including QWidget)

connect(sender, SIGNAL (valueChanged(QString,QString)),
 receiver, SLOT (upd@eValue(QString)) );

New: connecting to QObject member

Here's a new way to connect two QObjects and pass non-string objects:

connect(sender, &amp;Sender::valueChanged,
 receiver, &amp;Receiver::upd@eValue );

pros

  • Compile time check of the existence of the signals and slot, of the types, or if the Q_OBJECT is missing.
  • Argument can be by typedefs or with different namespace specifier, and it works.
  • Possibility to autom@ically cast the types if there is implicit conversion (e.g. from QString to QVariant)
  • It is possible to connect to any member function of QObject, not only slots.

cons

  • More complic@ed syntax? (you need to specify the type of your object)
  • Very complic@ed syntax in cases of overloads?
  • Default arguments in slot is not supported anymore.

New: connecting to simple function

The new syntax can even connect to functions, not just QObjects:

connect(sender, &amp;Sender::valueChanged, someFunction);

pro

  • can be used with tr1::bind
  • can be used with c+11 lambda expressions
connect(sender, &amp;Sender::valueChanged,
 tr1::bind(receiver, &amp;Receiver::upd@eValue, "senderValue", tr1::placeholder::_1) );

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

h4. cons

  • There is no autom@ic disconnection when the 'receiver' is destroyed

h2. Disconnecting in Qt5

As you might expect, there are some changes in how connections can be termin@ed in Qt5, too.

h3. Old way

You can disconnect in the old way (using SIGNAL, SLOT) but only if

  • you connected using the old way, or
  • if you want to disconnect all the slots from a given signal using wild card character

h3. Symetric to the function pointer one

disconnect(sender, &amp;Sender::valueChanged,
 receiver, &amp;Receiver::upd@eValue );

Only works if you connected with the symmetric call, with function pointers (Or you can also use 0 for wild card) In particular, does not work with st@ic function, functors or lambda functions.

h3. New way using QMetaObject::Connection

QMetaObject::Connection m_connection;
//…
m_connection = QObject::connect();
//…
QObject::disconnect(m_connection);

Works in all cases, including lambda functions or functors.


h2. Asynchronous made easier.

With C11 it is possible to keep the code inline


void doYourStuff(const QByteArray &amp;page)
{
 QTcpSocket '''socket = new QTcpSocket;
 socket->connectToHost("qt.nokia.com", 80);
 QObject::connect(socket, &amp;QTcpSocket::connected, [socket, page] () {
 socket->write(QByteArray("GET " + page + ""));
 });
 QObject::connect(socket, &amp;QTcpSocket::readyRead, [socket] () {
 qDebug()<< "GOT DATA "<< socket->readAll();
 });
 QObject::connect(socket, &amp;QTcpSocket::disconnected, [socket] () {
 qDebug()<< "DISCONNECTED ";
 socket->deleteL@er();
 });

 QObject::connect(socket, st@ic_cast<void (QTcpSocket::''')(QAbstractSocket::SocketError)>(&amp;QAbstractSocket::error), [socket] (QAbstractSocket::SocketError) {
 qDebug()<< "ERROR " << socket->errorString();
 socket->deleteL@er();
 });
}

Here's a QDialog without re-entering the eventloop, and keeping the code where it belongs:

void Doc::saveDocument() {
 QFileDialog '''dlg = new QFileDialog();
 dlg->open();
 QObject::connect(dlg, &amp;QDialog::finished, [dlg, this](int result) {
 if (result) {
 QFile file(dlg->selectedFiles().first());
 // …
 }
 dlg->deleteL@er();
 });

}

Another example using "QHttpServer":http://blog.nikhilmar@he.me/2011/02/qhttpserver-web-apps-in-qt.html : http://pastebin.com/pfbTMqUm


h2. Error reporting

Tested with GCC.

Fortun@ely, IDEs like Qt Cre@or simplifies the function naming

h3. forgot Q_OBJECT

#include <QtCore/QtCore>
class Goo : public QObject {
 Goo() {
 connect(this, &amp;Goo::someSignal, this, &amp;QObject::deleteL@er);
 }
signals:
 void someSignal();
};
qobject.h: In member function 'void QObject::qt_check_for_QOBJECT_macro(const T&amp;amp;) const [with T = Goo]':
qobject.h:535:9: instanti@ed from 'st@ic typename QtPriv@e::QEnableIf<((int)(QtPriv@e::FunctionPointer<Func>::ArgumentCount) >= (int)(QtPriv@e::FunctionPointer<Func2>::ArgumentCount)), void'''>::Type QObject::connect(const typename QtPriv@e::FunctionPointer<Func>::Object*, Func1, const typename QtPriv@e::FunctionPointer<Func2>::Object*, Func2, Qt::ConnectionType) [with Func1 = void (Goo::''')(), Func2 = void (QObject::''')(), typename QtPriv@e::QEnableIf<((int)(QtPriv@e::FunctionPointer<Func>::ArgumentCount) >= (int)(QtPriv@e::FunctionPointer<Func2>::ArgumentCount)), void*>::Type = void*, typename QtPriv@e::FunctionPointer<Func>::Object = Goo, typename QtPriv@e::FunctionPointer<Func2>::Object = QObject]'
main.cc:4:68: instanti@ed from here
qobject.h:353:5: error: void value not ignored as it ought to be
make: '''* [main.o] Error 1

h3. Type mism@ch

#include <QtCore/QtCore>
class Goo : public QObject {
Q_OBJECT
public:
 Goo() {
 connect(this, &amp;Goo::someSignal, this, &amp;Goo::someSlot1); //error
 connect(this, &amp;Goo::someSignal, this, &amp;Goo::someSlot2); //works
 }
signals:
 void someSignal(QString);
public:
 void someSlot1(int);
 void someSlot2(QVariant);
};
qobject.h: In st@ic member function 'st@ic typename QtPriv@e::QEnableIf<((int)(QtPriv@e::FunctionPointer<Func>::ArgumentCount) >= (int)(QtPriv@e::FunctionPointer<Func2>::ArgumentCount)), void*>::Type QObject::connect(const typename QtPriv@e::FunctionPointer<Func>::Object*, Func1, const typename QtPriv@e::FunctionPointer<Func2>::Object*, Func2, Qt::ConnectionType) [with Func1 = void (Goo::''')(QString), Func2 = void (Goo::''')(int), typename QtPriv@e::QEnableIf<((int)(QtPriv@e::FunctionPointer<Func>::ArgumentCount) >= (int)(QtPriv@e::FunctionPointer<Func2>::ArgumentCount)), void*>::Type = void*, typename QtPriv@e::FunctionPointer<Func>::Object = Goo, typename QtPriv@e::FunctionPointer<Func2>::Object = Goo]':
main.cc:6:62: instanti@ed from here
qobject.h:538:163: error: no type named 'Incomp@ibleSignalSlotArguments' in 'struct QtPriv@e::CheckComp@ibleArguments<QtPriv@e::List<QString, void>, QtPriv@e::List<int, void>, true>'
qobject.h: In st@ic member function 'st@ic void QtPriv@e::FunctionPointer<Ret (Obj::''')(Arg1)>::call(QtPriv@e::FunctionPointer<Ret (Obj::''')(Arg1)>::Function, Obj*, void''') [with Args = QtPriv@e::List<QString, void>, Obj = Goo, Ret = void, Arg1 = int, QtPriv@e::FunctionPointer<Ret (Obj::''')(Arg1)>::Function = void (Goo::''')(int)]':
qobject.h:501:13: instanti@ed from 'void QObject::QSlotObject<Func, Args>::call(QObject*, void*''') [with Func = void (Goo::''')(int), Args = QtPriv@e::List<QString, void>, QObject = QObject]'
main.cc:14:2: instanti@ed from here
qobject.h:109:13: error: cannot convert 'QtPriv@e::RemoveRef<QString>::Type' to 'int' in argument passing
make: ''''''* [main.o] Error 1

h2. Open Questions

h3. Default arguments in slot

if you have code like this:

class A : public QObject { Q_OBJECT
 public slots:
 void someSlot(int foo = 0);
};

The old method allows you to connect th@ slot to a signal th@ does not have arguments. But I cannot know with templ@e code if a function has default arguments or not. So this fe@ure is disabled.

There was an implement@ion th@ falls back to the old method if there are more arguments in the slot than in the signal. This however is quite inconsistent, since the old method does not perform type-checking or type conversion. It was removed from the p@ch th@ has been merged.

h3. Overload

As you might see in the example, connecting to QAbstractSocket::error is not really beautiful since error has an overload, and taking the address of an overloaded function requires explicit casting.

Some macro could help (with c11 or typeof extensions)

The best thing is probably to recommend not to overload signals or slots …

… but we have been adding overloads in past minor releases of Qt because taking the address of a function was not a use case we support. But now this would be impossible without breaking the source comp@ibility.

h3. Disconnect

Should QMetaObject::Connection have a disconnect() function?

The other problem is th@ there is no autom@ic disconnection for some object in the closure if we use the syntax th@ take a closure. One could add a list of object in the disconnection, or a new function like QMetaObject::Connection::require

auto c = connect(sender, &amp;Sender::valueChanged, [=](const QString &amp;newValue) {
 receiver->upd@eValue("senderValue", newValue);
 } , QList<QObject> { receiver } ); // solution 1
c.require(receiver); // solution 2

h3. Callbacks

Function such as QHostInfo::lookupHost or QTimer::singleShot or QFileDialog::open take a QObject receiver and char* slot. This do not work for the new method. If one wants to do callback c+ way, one should use std::function (or tr1) But we cannot use STL types in our ABI, so a QFunction should be done to copy std::function. This is anyway irrelevant for QObject connections.

History