1

Hi I am trying to implement one time connection. It is asked also here but I need to implement it for the syntax (sender, signal, receiver, lambda ) because my lambdas are capturing something from receiver even this is onetime connection I do not want connection to be called after receiver is destroyed. My code so far is as follows :

    template <typename Func1, typename Func2, typename std::enable_if_t<std::is_member_pointer<Func2>::value, int> = 0>
static inline QMetaObject::Connection weakConnect(typename QtPrivate::FunctionPointer<Func1>::Object* sender,
                                                  Func1 signal,
                                                  typename QtPrivate::FunctionPointer<Func2>::Object* receiver,
                                                  Func2 slot)
{
    QMetaObject::Connection conn_normal = QObject::connect(sender, signal, receiver, slot);

    QMetaObject::Connection* conn_delete = new QMetaObject::Connection();

    *conn_delete = QObject::connect(sender, signal, [conn_normal, conn_delete]() {
        QObject::disconnect(conn_normal);
        QObject::disconnect(*conn_delete);
        delete conn_delete;
    });
    return conn_normal;
}

template <typename Func1, typename Func2, typename std::enable_if_t<!std::is_member_pointer<Func2>::value, int> = 0>
static inline QMetaObject::Connection weakConnect(typename QtPrivate::FunctionPointer<Func1>::Object* sender,
                                                  Func1 signal,
                                                  Func2 slot)
{
    QMetaObject::Connection conn_normal = QObject::connect(sender, signal, slot);

    QMetaObject::Connection* conn_delete = new QMetaObject::Connection();

    *conn_delete = QObject::connect(sender, signal, [conn_normal, conn_delete]() {
        QObject::disconnect(conn_normal);
        QObject::disconnect(*conn_delete);
        delete conn_delete;
    });
    return conn_normal;
}

template <typename Func1, typename Func2, typename std::enable_if_t<!std::is_member_pointer<Func2>::value, int> = 0>
static inline QMetaObject::Connection weakConnect(typename QtPrivate::FunctionPointer<Func1>::Object* sender,
                                                  Func1 signal,
                                                  typename QtPrivate::FunctionPointer<Func2>::Object* receiver,
                                                  Func2 slot)
{
    Q_UNUSED(receiver);
    QMetaObject::Connection conn_normal = QObject::connect(sender, signal, slot);

    QMetaObject::Connection* conn_delete = new QMetaObject::Connection();

    *conn_delete = QObject::connect(sender, signal, [conn_normal, conn_delete]() {
        QObject::disconnect(conn_normal);
        QObject::disconnect(*conn_delete);
        delete conn_delete;
    });
    return conn_normal;
}

The problem is with 3rd overload. Because even lambda is not a member function, compilers is defining lambda type as : Class::function::lambda if I create lambda inside Class::function() if I remove is_member check then it becomes redefinition of 1st overload. How can I make this template to work ?

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
Muhammet Ali Asan
  • 1,486
  • 22
  • 39
  • What's the point of having `receiver` just to put `Q_UNUSED(receiver);` ? This `QtPrivate::FunctionPointer::Object` substitution fails for lambdas, which makes third overload not viable – Piotr Skotnicki Sep 05 '19 at 21:57
  • In the third overload, you assert that `Func2` is not in fact a member pointer - then go ahead and attempt to treat it as one and extract the class whose member it's pointing to (for `receiver`). That doesn't make any sense. If you want `receiver` to be an arbitrary pointer, introduce a separate template parameter for it. Or perhaps you want it to be `QObject*`, so you could connect to its `destroyed` signal. – Igor Tandetnik Sep 08 '19 at 18:07
  • There's [`QObject::connect` overload](https://doc.qt.io/qt-5/qobject.html#connect-5) that takes `QObject* context` and a lambda for the slot. That connection is automatically disconnected when `context` is destroyed. Seems like the one you would want for your third overload. – Igor Tandetnik Sep 08 '19 at 18:14

0 Answers0