Search code examples
c++qtcallbackqt5function-object

Qt5 Function object as callback copying


I tried the new Qt5 feature of using a callable object as callback.

#include <QApplication>
#include <QPushButton>
#include <QWidget>
#include <QBoxLayout>

#include <cstdio>

class ButtonEventHandler
    {
    public:
        ButtonEventHandler(const ButtonEventHandler& obj):
            counter(obj.counter),r_button(obj.r_button)
            {
            printf("Copy from %p -> %p\n",&obj,this);
            }

        ButtonEventHandler& operator=(const ButtonEventHandler& obj)
            {
            r_button=obj.r_button;
            counter=obj.counter;
            printf("Assign from %p -> %p\n",&obj,this);
            return *this;
            }

        explicit ButtonEventHandler(QPushButton& button):r_button(&button)
            {
            printf("CTOR %p\n",this);
            counter=0;
            }

        void operator()(bool checked) noexcept
            {
            char buffer[32];
            printf("%p  counter:%zu\n",this,counter);
            sprintf(buffer,"%zu",counter);
            r_button->setText(buffer);
            ++counter;
            }

    private:
        size_t counter;
        QPushButton* r_button;
    };

int main(int argc,char** argv)
    {
    QApplication app(argc,argv);
    QWidget window;
    QHBoxLayout box;
    window.setLayout(&box);
    window.setFixedSize(400,300);

    QPushButton button1("Click me");
    ButtonEventHandler eh1(button1);
    QObject::connect(&button1,&QPushButton::clicked,eh1);
    box.addWidget(&button1);

    window.show();
    return app.exec();
    }

Sample output:

CTOR 0x7ffdd35f4ed0
Copy from 0x7ffdd35f4ed0 -> 0x7ffdd35f4ee0
Copy from 0x7ffdd35f4ee0 -> 0x7ffdd35f4e70
Copy from 0x7ffdd35f4e70 -> 0x21b2c10
Copy from 0x21b2c10 -> 0x7ffdd35f4050
0x7ffdd35f4050  counter:0
Copy from 0x21b2c10 -> 0x7ffdd35f4050
0x7ffdd35f4050  counter:0
Copy from 0x21b2c10 -> 0x7ffdd35f4050
0x7ffdd35f4050  counter:0
Copy from 0x21b2c10 -> 0x7ffdd35f4050
0x7ffdd35f4050  counter:0

However, it does not really behave as expected. It starts with copying the callback object (I understand that: so it does not go out of scope before the object it is associated with). But then, the object is copied before every fired event, so my counter is kept at zero. Why does it keep the object invariant?


Solution

  • It appears that this is a bug in Qt 5.5.1. Compiling against Qt 5.7 gives the following output:

    CTOR 0x7ffd7a47e370
    Copy from 0x7ffd7a47e370 -> 0x7ffd7a47e380
    Copy from 0x7ffd7a47e380 -> 0x7ffd7a47e310
    Copy from 0x7ffd7a47e310 -> 0xb65970
    0xb65970  counter:0
    0xb65970  counter:1
    0xb65970  counter:2
    

    Which is more expected