[Interest] Convert to QMetaMethod from QObject + const char *

Alexey Rusakov ktirf at users.sf.net
Wed Aug 17 16:03:50 CEST 2022


Scott,

I guess the trick is to pass SIGNAL() as the second argument, rather
than a function or a function object. If you have the specific signal
passed to connect() (not a parameter passed from outside) then the
following might work for you (assuming C++17):


template <class ReceiverT, typename SlotT>
void func(..., ReceiverT* receiver, SlotT slot)
{
    // logic
    // The below assumes that `sender` points to an object of type
    // `Sender` with a signal `void trigger()`; make sure to change
    // it in both if constexpr branches
    if constexpr (std::is_same_v<SlotT, const char*>) {
        QObject::connect(sender, SIGNAL(trigger()), receiver, slot);
    }  else
        QObject::connect(sender, &Sender::trigger, receiver, slot);
    // more logic
}

(after playing around, looking at values in the debugger and studying
the relevant pieces of the Qt source code)
Actually, you can extract QMetaMethod out of whatever SIGNAL()/SLOT()
gives you if you're ok to rely on the undocumented format of the string
yielded by those macros, which is "NmethodName(Type1, Type2...)"
where N is a single digit encoding whether it's a signal or a slot. So
basically it could look like:

template <class ReceiverT, typename SlotT>
void func(..., ReceiverT* receiver, SlotT slot)
{
    // logic
    const auto signal = &Sender::trigger; // Put the signal pmf here
    if constexpr (std::is_same_v<SlotT, const char*>) {
        ++slot; // skip the code - relies on the internal Qt logic
        const auto& rmo = receiver->metaObject();
        const int slotIndex = rmo->indexOfSlot(slot);
        Q_ASSERT(slotIndex >= 0);
        QObject::connect(..., QMetaMethod::fromSignal(signal),
                         receiver, rmo->method(slotIndex));
    }  else
        QObject::connect(..., signal, receiver, slot);
    // more logic
}

Alexey Rusakov

-----Original Message-----
From: Volker Hilsheimer <volker.hilsheimer at qt.io>
To: Scott Bloom <scott at towel42.com>
Cc: interest at qt-project.org <interest at qt-project.org>
Subject: Re: [Interest] Convert to QMetaMethod from QObject + const
char *
Date: Wed, 17 Aug 2022 09:23:37 +0000

> On 16 Aug 2022, at 22:39, Scott Bloom <scott at towel42.com> wrote:
> 
> I have a function that takes in a QObject and const char *
> signal/slot
>  
> void func( …, QObject * target, const char * member )
> {
> …. logic
> QObject::connect( ….., target, member )
> … more logic
> {
>  
>  
> So I can call it via
>  
> ….
> func( …., m_target, SLOT( XXXX )
>>  
> it works fine
>  
> I would like to modify the function so it can also take
>  
> func( …., m_target, &TargetClass::XXXX 
>  
> 
> however, I cant for the life of me figure out to convert, if its even
> possible
>  
> Id prefer not to have to copy all the logic in func
>  
> Is this possible?
> 
> Yes, I know I can use std::enable_if, but that just copies the
> function logic
> 
> Thanks
> Scott


Check QHostInfo::lookupHost for a Qt API that does that. It relies on
private Qt APIs though.

There might be C++17-ways to simplify some of that using `if
constexpr`, but the basics will probably be the same.

Volker

_______________________________________________
Interest mailing list
Interest at qt-project.org
https://lists.qt-project.org/listinfo/interest



More information about the Interest mailing list