如何构造一个具有可变参数指针函数的类作为成员?

时间:2017-04-07 15:19:45

标签: c++ templates variadic

我想知道C ++中是否可以使用以下内容。我需要构造一个类,它将作为数据成员存储std::map,键的类型为std::string,值为函数指针。问题是我希望这些函数指针是可变的,因为它们应该指向接受任意数量参数的函数,即指向函数的形式

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

重要的一点是,我希望能够为我的类的给定实例的映射中的不同函数指针设置不同的参数。例如,我可能想要创建我的类的对象并使其映射包含两对,一个对应于具有(double, int)作为参数的函数,另一个对应具有(std::vector, int, int)作为参数。我希望能够做到这一点,因为我希望能够向地图添加新元素,可能有不同的参数列表(虽然我只会在编译时这样做,但我仍然需要编码因为我想从其他文件/客户端添加新元素,所以该类不知道类型。

实现此目的的最佳方法是什么?

1 个答案:

答案 0 :(得分:0)

对于那些说你不能的人,你实际上可以,它不漂亮:

这是来自moc工具输出的示例代码,它完全相同:它存储任意数量的函数/方法指针,具有任意数量的参数。

最简单的解决方案:只需使用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;
            }
        }
    }
}