Qt-interest Archive, March 2002
Possible slot/signal connection bug, 'const' ignored
Message 1 in thread
I have two slots both called 'invoke()', one takes a 'QByteArray&' and the
other takes a 'const QByteArray&' argument. If I connect a signal of type
'const QByteArray&' to the slot of type 'const QByteArray&', the wrong slot
is called - the non-const slot of type 'QByteArray&'.
signals:
void testSignal1(QByteArray&);
void testSignal2(const QByteArray&);
public slots:
void invoke(QByteArray&);
void invoke(const QByteArray&);
...
connect(this,SIGNAL(testSignal1(QByteArray&)),
this, SLOT(invoke(QByteArray&)));
connect(this,SIGNAL(testSignal2(const QByteArray&)),
this, SLOT(invoke(const QByteArray&)));
...
void TestMOC::invoke(QByteArray& arg)
{
printf("In slotTest1()\n");
}
void TestMOC::invoke(const QByteArray& arg)
{
printf("In slotTest2()\n");
}
QByteArray test;
emit(testSignal1(test));
emit(testSignal2(test));
Produces the following output:
In slotTest1()
In slotTest1()
I am using the current version of qt-copy from the KDE cvs.
-- Richard
Message 2 in thread
I made just a same example you wrote and executed with g++
(gcc version 2.95.4) and qt-x11-2.3.1 on GNU/Linux.
To my surprise the output was:
In slotTest1()
In slotTest2()
Please check QMetaObject* TestMOC::staticMetaObject() in
TestMOC.moc.cpp.
If my case the slot_tbl was initialized like:
slot_tbl[0].name = "invoke(QByteArray&)";
slot_tbl[0].ptr = (QMember)ov1_0;
slot_tbl_access[0] = QMetaData::Public;
slot_tbl[1].name = "invoke(const QByteArray&)";
slot_tbl[1].ptr = (QMember)ov1_1;
slot_tbl_access[1] = QMetaData::Public;
On 2002 March 23 Saturday 00:32, Richard Dale wrote:
> I have two slots both called 'invoke()', one takes a
> 'QByteArray&' and the other takes a 'const QByteArray&'
> argument. If I connect a signal of type 'const
> QByteArray&' to the slot of type 'const QByteArray&', the
> wrong slot is called - the non-const slot of type
> 'QByteArray&'.
>
> signals:
> void testSignal1(QByteArray&);
> void testSignal2(const QByteArray&);
> public slots:
> void invoke(QByteArray&);
> void invoke(const QByteArray&);
> ...
>
> connect(this,SIGNAL(testSignal1(QByteArray&)),
> this, SLOT(invoke(QByteArray&)));
>
> connect(this,SIGNAL(testSignal2(const QByteArray&)),
> this, SLOT(invoke(const QByteArray&)));
> ...
>
> void TestMOC::invoke(QByteArray& arg)
> {
> printf("In slotTest1()\n");
> }
>
> void TestMOC::invoke(const QByteArray& arg)
> {
> printf("In slotTest2()\n");
> }
>
> QByteArray test;
> emit(testSignal1(test));
> emit(testSignal2(test));
>
> Produces the following output:
>
> In slotTest1()
> In slotTest1()
>
> I am using the current version of qt-copy from the KDE
> cvs.
>
> -- Richard
Message 3 in thread
Hi Richard
I am really wondering why this code is compiling. According to the
Stroustrup bible (The C++ Programming Language, chapter 7.4 (Overloaded
Function Names)), the type for the overloaded function should differ by more
than just by constness.
But now I made a small example and the compiler can really handle that! I
checked it with g++ on Linux and with the MIPSpro compiler on Irix.
What I believe is that in the signal/slot case the arguments must differ
more than just by constness.
Hope that helped.
With kind regards
Beat Schaer
> -----Original Message-----
> From: Richard Dale [mailto:Richard_Dale@tipitina.demon.co.uk]
> Sent: Friday, March 22, 2002 4:32 PM
> To: QT-Interest
> Subject: Possible slot/signal connection bug, 'const' ignored
>
>
> I have two slots both called 'invoke()', one takes a
> 'QByteArray&' and the
> other takes a 'const QByteArray&' argument. If I connect a
> signal of type
> 'const QByteArray&' to the slot of type 'const QByteArray&',
> the wrong slot
> is called - the non-const slot of type 'QByteArray&'.
>
> signals:
> void testSignal1(QByteArray&);
> void testSignal2(const QByteArray&);
> public slots:
> void invoke(QByteArray&);
> void invoke(const QByteArray&);
> ...
>
> connect(this,SIGNAL(testSignal1(QByteArray&)),
> this, SLOT(invoke(QByteArray&)));
>
> connect(this,SIGNAL(testSignal2(const QByteArray&)),
> this, SLOT(invoke(const QByteArray&)));
> ...
>
> void TestMOC::invoke(QByteArray& arg)
> {
> printf("In slotTest1()\n");
> }
>
> void TestMOC::invoke(const QByteArray& arg)
> {
> printf("In slotTest2()\n");
> }
>
> QByteArray test;
> emit(testSignal1(test));
> emit(testSignal2(test));
>
> Produces the following output:
>
> In slotTest1()
> In slotTest1()
>
> I am using the current version of qt-copy from the KDE cvs.
>
> -- Richard
>
> --
> List archive and information: http://qt-interest.trolltech.com
>
Message 4 in thread
> Hi Richard
>
> I am really wondering why this code is compiling. According to the
> Stroustrup bible (The C++ Programming Language, chapter 7.4 (Overloaded
> Function Names)), the type for the overloaded function should differ by
more
> than just by constness.
>
Thats strange, since Stroustrup takes the trouble to explain it very clearly
in the ARM.
This is illegal:
int f(int i)
{
...
}
int f(const int i)
{
...
}
But this is OK:
int f(int& i)
{
...
}
int f(const int& i)
{
...
}
> But now I made a small example and the compiler can really handle that! I
> checked it with g++ on Linux and with the MIPSpro compiler on Irix.
>
> What I believe is that in the signal/slot case the arguments must differ
> more than just by constness.
>
> Hope that helped.
>
> With kind regards
> Beat Schaer
>
>
> > -----Original Message-----
> > From: Richard Dale [mailto:Richard_Dale@tipitina.demon.co.uk]
> > Sent: Friday, March 22, 2002 4:32 PM
> > To: QT-Interest
> > Subject: Possible slot/signal connection bug, 'const' ignored
> >
> >
> > I have two slots both called 'invoke()', one takes a
> > 'QByteArray&' and the
> > other takes a 'const QByteArray&' argument. If I connect a
> > signal of type
> > 'const QByteArray&' to the slot of type 'const QByteArray&',
> > the wrong slot
> > is called - the non-const slot of type 'QByteArray&'.
> >
> > signals:
> > void testSignal1(QByteArray&);
> > void testSignal2(const QByteArray&);
> > public slots:
> > void invoke(QByteArray&);
> > void invoke(const QByteArray&);
> > ...
> >
> > connect(this,SIGNAL(testSignal1(QByteArray&)),
> > this, SLOT(invoke(QByteArray&)));
> >
> > connect(this,SIGNAL(testSignal2(const QByteArray&)),
> > this, SLOT(invoke(const QByteArray&)));
> > ...
> >
> > void TestMOC::invoke(QByteArray& arg)
> > {
> > printf("In slotTest1()\n");
> > }
> >
> > void TestMOC::invoke(const QByteArray& arg)
> > {
> > printf("In slotTest2()\n");
> > }
> >
> > QByteArray test;
> > emit(testSignal1(test));
> > emit(testSignal2(test));
> >
> > Produces the following output:
> >
> > In slotTest1()
> > In slotTest1()
> >
> > I am using the current version of qt-copy from the KDE cvs.
> >
> > -- Richard
> >
> > --
> > List archive and information: http://qt-interest.trolltech.com
> >
>
> --
> List archive and information: http://qt-interest.trolltech.com
Message 5 in thread
On Friday 22 March 2002 4:56 pm, Paul Robertson wrote:
> > On Friday 22 March 2002 4:26 pm, beat.schaer@ruag.com wrote:
> > I am really wondering why this code is compiling. According to the
> > Stroustrup bible (The C++ Programming Language, chapter 7.4 (Overloaded
> > Function Names)), the type for the overloaded function should differ by
> > more
> > than just by constness.
>
> Thats strange, since Stroustrup takes the trouble to explain it very
> clearly in the ARM.
>
> This is illegal:
>
> int f(int i)
> {
> ...
> }
> int f(const int i)
> {
> ...
> }
>
> But this is OK:
>
> int f(int& i)
> {
> ...
> }
> int f(const int& i)
> {
> ...
> }
>
> > But now I made a small example and the compiler can really handle that! I
> > checked it with g++ on Linux and with the MIPSpro compiler on Irix.
> >
> > What I believe is that in the signal/slot case the arguments must differ
> > more than just by constness.
The problem is a bug in the Qt 3.x moc. It generates two function calls
'qt_invoke()' and 'qt_emit()'.
bool TestMOC::qt_invoke( int _id, QUObject* _o )
{
switch ( _id - staticMetaObject()->slotOffset() ) {
case 0: invoke(*((QByteArray*)static_QUType_ptr.get(_o+1))); break;
case 1: invoke(*((QByteArray*)static_QUType_ptr.get(_o+1))); break;
...
bool TestMOC::qt_emit( int _id, QUObject* _o )
{
switch ( _id - staticMetaObject()->signalOffset() ) {
case 0: testSignal1(*((QByteArray*)static_QUType_ptr.get(_o+1))); break;
case 1: testSignal2(*((QByteArray*)static_QUType_ptr.get(_o+1))); break;
The same invoke() slot is called for both 'QByteArray&' and 'const
QByteArray&', and similarly the signals 'testSignal1' and 'testSignal2' have
the same type. The generated code needs to be changed to add an appropriate
cast for const/non-const reference types to ensure that overloading works
correctly:
bool TestMOC::qt_invoke( int _id, QUObject* _o )
{
switch ( _id - staticMetaObject()->slotOffset() ) {
case 0: invoke((QByteArray&)*((QByteArray*)static_QUType_ptr.get(_o+1)));
break;
case 1: invoke((const
QByteArray&)*((QByteArray*)static_QUType_ptr.get(_o+1))); break;
...
bool TestMOC::qt_emit( int _id, QUObject* _o )
{
switch ( _id - staticMetaObject()->signalOffset() ) {
case 0:
testSignal1((QByteArray&)*((QByteArray*)static_QUType_ptr.get(_o+1))); break;
case 1: testSignal2((const
QByteArray&)*((QByteArray*)static_QUType_ptr.get(_o+1))); break;
...
I've attached a small patch for the moc which fixes the problem. Copy
'moc_constref.patch' to $QTDIR/src
$ cd $QTDIR/src/moc
$ patch -p1 < ../moc_constref.patch
Then build Qt as normal.
-- Richard
> > > -----Original Message-----
> > > From: Richard Dale [mailto:Richard_Dale@tipitina.demon.co.uk]
> > > Sent: Friday, March 22, 2002 4:32 PM
> > > To: QT-Interest
> > > Subject: Possible slot/signal connection bug, 'const' ignored
> > >
> > >
> > > I have two slots both called 'invoke()', one takes a
> > > 'QByteArray&' and the
> > > other takes a 'const QByteArray&' argument. If I connect a
> > > signal of type
> > > 'const QByteArray&' to the slot of type 'const QByteArray&',
> > > the wrong slot
> > > is called - the non-const slot of type 'QByteArray&'.
> > >
> > > signals:
> > > void testSignal1(QByteArray&);
> > > void testSignal2(const QByteArray&);
> > > public slots:
> > > void invoke(QByteArray&);
> > > void invoke(const QByteArray&);
> > > ...
> > >
> > > connect(this,SIGNAL(testSignal1(QByteArray&)),
> > > this, SLOT(invoke(QByteArray&)));
> > >
> > > connect(this,SIGNAL(testSignal2(const QByteArray&)),
> > > this, SLOT(invoke(const QByteArray&)));
> > > ...
> > >
> > > void TestMOC::invoke(QByteArray& arg)
> > > {
> > > printf("In slotTest1()\n");
> > > }
> > >
> > > void TestMOC::invoke(const QByteArray& arg)
> > > {
> > > printf("In slotTest2()\n");
> > > }
> > >
> > > QByteArray test;
> > > emit(testSignal1(test));
> > > emit(testSignal2(test));
> > >
> > > Produces the following output:
> > >
> > > In slotTest1()
> > > In slotTest1()
> > >
> > > I am using the current version of qt-copy from the KDE cvs.
> > >
> > > -- Richard
> > >
> > > --
> > > List archive and information: http://qt-interest.trolltech.com
> >
> > --
> > List archive and information: http://qt-interest.trolltech.com
diff -Naur -X /home/duke/bin/patcher.exclude temp/moc.y moc/moc.y
--- temp/moc.y Sun Mar 24 04:02:21 2002
+++ moc/moc.y Sun Mar 24 04:12:34 2002
@@ -3253,7 +3253,7 @@
else
fprintf( out, "static_QUType_%s.get(_o+%d)", utype.data(), offset+1 );
} else {
- fprintf( out, "*((%s*)static_QUType_ptr.get(_o+%d))", referencePlainUType( type) .data(), offset+1 );
+ fprintf( out, "(%s)*((%s*)static_QUType_ptr.get(_o+%d))", type.data(), referencePlainUType( type) .data(), offset+1 );
}
a = f->args->next();
if ( a )
@@ -3321,7 +3321,7 @@
else
fprintf( out, "static_QUType_%s.get(_o+%d)", utype.data(), offset+1 );
} else {
- fprintf( out, "*((%s*)static_QUType_ptr.get(_o+%d))", referencePlainUType(type).data(), offset+1 );
+ fprintf( out, "(%s)*((%s*)static_QUType_ptr.get(_o+%d))", type.data(), referencePlainUType(type).data(), offset+1 );
}
a = f->args->next();
if ( a )
Message 6 in thread
On Friday 22 March 2002 4:26 pm, beat.schaer@ruag.com wrote:
> I am really wondering why this code is compiling. According to the
> Stroustrup bible (The C++ Programming Language, chapter 7.4 (Overloaded
> Function Names)), the type for the overloaded function should differ by
> more than just by constness.
>
> But now I made a small example and the compiler can really handle that! I
> checked it with g++ on Linux and with the MIPSpro compiler on Irix.
>
> What I believe is that in the signal/slot case the arguments must differ
> more than just by constness.
>
> Hope that helped.
Well yes, but I've still got a problem which I'll need to work round in one of
two ways. Either rename the slots 'invokeconst' if they contain a const
string, or make do with just the non-const slot types. I've just tried the
code with Qt-2.3.2 (as opposed to Qt 3.0.3) and my example used to work.
Here is a comment from qobject.cpp about the behaviour of Qt when matching
slot/signal type signatures with const modifiers in them:
/*!
\fn bool QObject::checkConnectArgs( const char *signal, const QObject
*receiver, const char *member )
Returns TRUE if the \a signal and the \a member arguments are compatible;
otherwise returns FALSE. (The \a receiver argument is currently ignored.)
\warning
We recommend that you use the default implementation and do not
reimplement this function.
\omit
TRUE: "signal(<anything>)", "member()"
TRUE: "signal(a,b,c)", "member(a,b,c)"
TRUE: "signal(a,b,c)", "member(a,b)", "member(a)" etc.
FALSE: "signal(const a)", "member(a)"
FALSE: "signal(a)", "member(const a)"
FALSE: "signal(a)", "member(b)"
FALSE: "signal(a)", "member(a,b)"
*/
bool QObject::checkConnectArgs( const char *signal,
...
If Qt didn't want to distiguish between them, wouldn't it just strip them out?
Then there would be no need for a comment like the one above.
-- Richard
> > -----Original Message-----
> > From: Richard Dale [mailto:Richard_Dale@tipitina.demon.co.uk]
> > Sent: Friday, March 22, 2002 4:32 PM
> > To: QT-Interest
> > Subject: Possible slot/signal connection bug, 'const' ignored
> >
> >
> > I have two slots both called 'invoke()', one takes a
> > 'QByteArray&' and the
> > other takes a 'const QByteArray&' argument. If I connect a
> > signal of type
> > 'const QByteArray&' to the slot of type 'const QByteArray&',
> > the wrong slot
> > is called - the non-const slot of type 'QByteArray&'.
> >
> > signals:
> > void testSignal1(QByteArray&);
> > void testSignal2(const QByteArray&);
> > public slots:
> > void invoke(QByteArray&);
> > void invoke(const QByteArray&);
> > ...
> >
> > connect(this,SIGNAL(testSignal1(QByteArray&)),
> > this, SLOT(invoke(QByteArray&)));
> >
> > connect(this,SIGNAL(testSignal2(const QByteArray&)),
> > this, SLOT(invoke(const QByteArray&)));
> > ...
> >
> > void TestMOC::invoke(QByteArray& arg)
> > {
> > printf("In slotTest1()\n");
> > }
> >
> > void TestMOC::invoke(const QByteArray& arg)
> > {
> > printf("In slotTest2()\n");
> > }
> >
> > QByteArray test;
> > emit(testSignal1(test));
> > emit(testSignal2(test));
> >
> > Produces the following output:
> >
> > In slotTest1()
> > In slotTest1()
> >
> > I am using the current version of qt-copy from the KDE cvs.
> >
> > -- Richard
> >
> > --
> > List archive and information: http://qt-interest.trolltech.com