2017-04-07 48 views
0

我想知道以下是否可能在C++中。我需要構造一個類,它將作爲數據成員存儲在std::map中,鍵的類型爲std::string,值爲函數指針。問題是,我想這些函數指針是可變參數在這個意義上,他們應該指向接受的參數指向形式的功能的任意數,即功能如何用可變指針函數構造一個類作爲成員?

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

最重要的一點是,我希望能夠爲我的類的給定實例的地圖中的不同函數指針提供不同的參數。例如,我可能想要創建我的類的對象,並讓它的映射包含兩個對,一個對應於具有(double, int)作爲參數的函數,另一個具有(std::vector, int, int)作爲參數。我希望能夠做到這一點,因爲我希望能夠添加新的元素到地圖中,可能會有不同的參數列表(儘管我只會在編譯時做到這一點,但我仍然需要編寫代碼該類不知道類型,因爲我想從其他文件/客戶端添加新元素)。

實現此目的的最佳方法是什麼?

+1

你會如何從該地圖調用函數?大多數解決方案都會降低任何編譯時類型的安全性。你可以使用'std :: any'來存儲你的函數指針嗎? –

+1

聽起來像是一種擦除類型的工作。 –

+0

一旦將'f'變成函數指針,它就是一個具有固定參數和類型的固定函數。您無法存儲模板。 – nwp

回答

0

對於所有那些說你不能,你居然能,它不漂亮:

這是交通部工具的輸出的示例代碼,這正是這麼做的:它存儲的功能的任意量/方法指針,具有任意數量的參數。

最簡單的解決方案:只需使用Qt的moc工具爲你生成, 如果你不能或不想使用Qt,你仍然可以分析下面的代碼來實現它。

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; 
      } 
     } 
    } 
} 
相關問題