2017-04-07 12 views
0

C++で次のことが可能かどうかを知りたい。私はstd::stringのキーを持つデータメンバーとしてstd::mapを格納するクラスを構築する必要があり、値は関数ポインタです。事は重要なビットは、私ということであるフォームバリアントポインタ関数を持つクラスをメンバにするには?

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

の機能を指し、すなわち、私はこれらの関数ポインタが、彼らは任意の数の引数を受け入れる機能を指している必要がありますという意味で可変引数になりたいということです私のクラスの特定のインスタンスのマップ内の異なる関数ポインタのために異なる引数を持つことができるようにしたい。たとえば、クラスのオブジェクトを作成し、そのマップに2つのペアを含めると、1つは(double, int)を引数とする関数に対応し、もう1つは(std::vector, int, int)を引数として持つことができます。おそらく異なる引数リストを使ってマップに新しい要素を追加できるようにしたいという意味で、この一般的なものを作りたいと思っています(私はコンパイル時にしか行いませんが、まだコードを書く必要があります私は他のファイル/クライアントからの新しい要素を追加したいので、型について知らないクラス)。

これを実装する最良の方法は何ですか?あなたが傾くと言って、すべての人のために

+1

どのようにしてそのマップから関数を呼び出しますか?ほとんどのソリューションは、あらゆる種類のコンパイル時の型安全性を低下させます。関数ポインタを格納するために 'std :: any'を使用できますか? –

+1

タイプ消去の仕事のように聞こえます。 –

+0

'f'を関数ポインタに変換すると、固定数のパラメータと型を持つ具象関数になります。テンプレートは保存できません。 – nwp

答えて

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; 
      } 
     } 
    } 
} 
関連する問題