2017-04-07 49 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; 
      } 
     } 
    } 
} 
相关问题