2017-04-07 2 views
0

Ich möchte wissen, ob das Folgende in C++ möglich ist. Ich muss eine Klasse erstellen, die als Datenelement eine std::map speichert, mit Schlüsseln vom Typ std::string, und Werte sind Funktionszeiger. Die Sache ist, dass ich diese Funktionszeiger in dem Sinne, variadische will, dass sie Funktionen anweisen, eine beliebige Anzahl von Argumenten akzeptieren, dh Hinweis auf Funktionen der FormWie konstruiere ich eine Klasse mit variablen Zeigerfunktionen als Mitglieder?

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

Das wichtige Bit ist, dass ich Ich möchte unterschiedliche Argumente für die verschiedenen Funktionszeiger in der Map einer bestimmten Instanz meiner Klasse haben können. Ich möchte zum Beispiel ein Objekt meiner Klasse erstellen und seine Map zwei Paare enthalten, von denen eines einer Funktion mit (double, int) als Argumente und einem anderen (std::vector, int, int) als Argumente entspricht. Und ich möchte in der Lage sein, dies allgemein zu machen, in dem Sinne, dass ich der Karte neue Elemente mit möglicherweise unterschiedlichen Argumentlisten hinzufügen kann (obwohl ich dies nur zur Kompilierzeit tun würde, muss ich immer noch programmieren die Klasse ohne die Typen zu kennen, da ich die neuen Elemente aus anderen Dateien/Clients hinzufügen möchte).

Was ist der beste Weg, dies zu implementieren?

+1

Wie würden Sie Funktionen von dieser Karte aufrufen? Die meisten Lösungen würden jegliche Art von Sicherheitsfunktionen für die Kompilierungszeit löschen. Kannst du 'std :: any' benutzen, um deine Funktionszeiger zu speichern? –

+1

Klingt wie ein Job für Typ löschen. –

+0

Sobald Sie 'f' in einen Funktionszeiger verwandeln, ist dies eine konkrete Funktion mit einer festen Anzahl von Parametern und Typen. Sie können keine Vorlage speichern. – nwp

Antwort

0

Für alle, sagen Sie können nicht, man kann tatsächlich, es nicht schön ist:

Dies ist ein Beispiel-Code aus dem Ausgang des moc-Tool, das genau das tut: Er speichert eine beliebige Menge an Funktion/Methode Zeiger mit einer beliebigen Anzahl von Argumenten.

Einfachste Lösung: Verwenden Sie einfach Qt Moc-Tool, um das für Sie zu generieren, Wenn Sie Qt nicht verwenden können oder wollen, können Sie noch den Code unten analysieren, wie sie es erreichen.

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; 
      } 
     } 
    } 
} 
Verwandte Themen