2017-04-07 1 views
0

Je veux savoir si ce qui suit est possible en C++. J'ai besoin de construire une classe qui va stocker comme un membre de données un std::map, avec les clés étant de type std::string, et les valeurs étant des pointeurs de fonction. La chose est que je veux que ces pointeurs de fonction à variadique dans le sens où ils doivent pointer vers des fonctions acceptant un nombre arbitraire d'arguments, à savoir pointant vers des fonctions de la formeComment construire une classe avec des fonctions de pointeur variadique en tant que membres?

template<class... Args> f(Args...);

Le bit important est que je Je veux pouvoir avoir différents arguments pour les différents pointeurs de fonction dans la carte d'une instance donnée de ma classe. Par exemple, je pourrais vouloir créer un objet de ma classe et avoir sa carte contenant deux paires, une correspondant à une fonction ayant (double, int) comme arguments, et une autre ayant (std::vector, int, int) comme arguments. Et je veux être en mesure de rendre cela général, dans le sens où je veux pouvoir ajouter de nouveaux éléments à la carte, avec des listes d'arguments différentes (bien que je ne ferais cela qu'à la compilation, j'ai encore besoin de coder la classe sans connaître les types puisque je veux ajouter les nouveaux éléments d'autres fichiers/clients).

Quelle est la meilleure façon de mettre en œuvre cela?

+1

Comment appelleriez-vous les fonctions de cette carte? La plupart des solutions suppriment tout type de sécurité de type compilation. Pouvez-vous utiliser 'std :: any' pour stocker vos pointeurs de fonction? –

+1

Cela ressemble à un travail pour l'effacement de type. –

+0

Une fois que vous tournez 'f' dans un pointeur de fonction, c'est une fonction concrète avec un nombre fixe de paramètres et de types. Vous ne pouvez pas stocker un modèle. – nwp

Répondre

0

Pour tous ceux qui disent vous ne pouvez pas, vous pouvez en fait, ce n'est pas assez:

C'est un exemple de code à partir de la sortie de l'outil moc, qui fait exactement cela: Il stocke une quantité arbitraire de fonction/méthode pointeurs, avec un nombre arbitraire d'arguments.

Solution la plus simple: Utilisez simplement l'outil moc de Qt pour générer cela pour vous, Si vous ne pouvez pas ou ne voulez pas utiliser Qt, vous pouvez toujours analyser le code ci-dessous pour savoir comment ils l'atteignent.

int AtCore::qt_metacall(QMetaObject::Call _c, int _id, void **_a) 
{ 
    _id = QObject::qt_metacall(_c, _id, _a); 
    if (_id < 0) 
     return _id; 
    if (_c == QMetaObject::InvokeMetaMethod) { 
     if (_id < 25) 
      qt_static_metacall(this, _c, _id, _a); 
     _id -= 25; 
    } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) { 
     if (_id < 25) 
      *reinterpret_cast<int*>(_a[0]) = -1; 
     _id -= 25; 
    } 
    return _id; 
} 


void AtCore::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) 
{ 
    if (_c == QMetaObject::InvokeMetaMethod) { 
     AtCore *_t = static_cast<AtCore *>(_o); 
     Q_UNUSED(_t) 
     switch (_id) { 
     case 0: _t->printProgressChanged((*reinterpret_cast< const float(*)>(_a[1]))); break; 
     case 1: _t->receivedMessage((*reinterpret_cast< const QByteArray(*)>(_a[1]))); break; 
     case 2: _t->stateChanged((*reinterpret_cast< PrinterState(*)>(_a[1]))); break; 
     case 3: _t->print((*reinterpret_cast< const QString(*)>(_a[1]))); break; 
     case 4: _t->stop(); break; 
     case 5: _t->pause((*reinterpret_cast< const QString(*)>(_a[1]))); break; 
     case 6: _t->resume(); break; 
     case 7: _t->home((*reinterpret_cast< uchar(*)>(_a[1]))); break; 
     case 8: _t->home(); break; 
     case 9: _t->setExtruderTemp((*reinterpret_cast< uint(*)>(_a[1])),(*reinterpret_cast< uint(*)>(_a[2]))); break; 
     case 10: _t->setExtruderTemp((*reinterpret_cast< uint(*)>(_a[1]))); break; 
     case 11: _t->setExtruderTemp(); break; 
     case 12: _t->move((*reinterpret_cast< uchar(*)>(_a[1])),(*reinterpret_cast< uint(*)>(_a[2]))); break; 
     case 13: _t->setBedTemp((*reinterpret_cast< uint(*)>(_a[1]))); break; 
     case 14: _t->setBedTemp(); break; 
     case 15: _t->setFanSpeed((*reinterpret_cast< uint(*)>(_a[1])),(*reinterpret_cast< uint(*)>(_a[2]))); break; 
     case 16: _t->setFanSpeed((*reinterpret_cast< uint(*)>(_a[1]))); break; 
     case 17: _t->setFanSpeed(); break; 
     case 18: _t->setAbsolutePosition(); break; 
     case 19: _t->setRelativePosition(); break; 
     case 20: _t->setPrinterSpeed((*reinterpret_cast< uint(*)>(_a[1]))); break; 
     case 21: _t->setPrinterSpeed(); break; 
     case 22: _t->setFlowRate((*reinterpret_cast< uint(*)>(_a[1]))); break; 
     case 23: _t->setFlowRate(); break; 
     case 24: _t->close(); break; 
     default: ; 
     } 
    } else if (_c == QMetaObject::IndexOfMethod) { 
     int *result = reinterpret_cast<int *>(_a[0]); 
     void **func = reinterpret_cast<void **>(_a[1]); 
     { 
      typedef void (AtCore::*_t)(const float &); 
      if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&AtCore::printProgressChanged)) { 
       *result = 0; 
       return; 
      } 
     } 
     { 
      typedef void (AtCore::*_t)(const QByteArray &); 
      if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&AtCore::receivedMessage)) { 
       *result = 1; 
       return; 
      } 
     } 
     { 
      typedef void (AtCore::*_t)(PrinterState); 
      if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&AtCore::stateChanged)) { 
       *result = 2; 
       return; 
      } 
     } 
    } 
}