Я собираюсь попытаться ответить самостоятельно, поскольку существующие ответы (большое спасибо @Mike Brown и @skyhisi) закладывают основу, но не рассматривают этот конкретный случай ...
Из источника:
QtConcurrent :: run (...) :
template <typename T, typename Class>
QFuture<T> run(const Class &object, T (Class::*fn)())
{
return (new QT_TYPENAME SelectStoredMemberFunctionCall0<T, Class>::type(fn, object))->start();
}
SelectStoredMemberFunctionCall0
template <typename T, typename Class>
struct SelectStoredMemberFunctionCall0
{
typedef typename SelectSpecialization<T>::template
Type<StoredMemberFunctionCall0 <T, Class>,
VoidStoredMemberFunctionCall0<T, Class> >::type type;
};
VoidStoredMemberFunctionCall0
template <typename T, typename Class>
class VoidStoredMemberFunctionCall0 : public RunFunctionTask<T>
{
public:
VoidStoredMemberFunctionCall0(T (Class::*_fn)() , const Class &_object)
: fn(_fn), object(_object){ }
void runFunctor()
{
(object.*fn)();
}
private:
T (Class::*fn)();
Class object;
};
Учитывая вышесказанное, я могу видеть, что Qt хранит функцию указателя на член обычным образом , но, перераспределяя ее в шаблоны, которые в противном случае остались бы незамеченными, иллюзия Несс создан.
Тип VoidStoredMemberFunctionCall0::object
, а также подпись VoidStoredMemberFunctionCall0::fn
указаны выше в аргументах, передаваемых QtConcurrent::run
.
Я не знал, что эта «неявная» шаблонизация была даже возможна, если честно. Кто-нибудь сможет порекомендовать дальнейшее чтение?