次の情報を持ついくつかのリフレクション メタデータがあるとします。
enum class type { t_int, t_double, t_str /* etc... */ };
struct meta_data
{
void* function;
void* instance;
std::vector<type> param_types;
};
std::map<std::string, meta_data> ftable;
関数名とパラメーターの両方を文字列として指定すると、このマップで関数を呼び出したいと思います。私の問題は、パラメーターを変換することではなく (たとえば、を使用boost::lexical_cast
)、正しいタイプの関数ポインターにキャストして関数を呼び出すことです。可能な 8 つの型と最大 8 つのパラメーターを許可する場合、それは既に私のコードに多くの分岐があります。避けたいこと (疑似コード):
スイッチ (md.param_types.size()) { ケース 0: 関数ポインタをキャストして呼び出す 壊す; ケース 1: スイッチ (md.param_types[0]) { ケースt_int: int param = boost::lexical_cast(param_strings[0]); 関数ポインタをキャストし、param で呼び出す 場合 ... } 壊す; ケース 2: スイッチ (md.param_types[0]) { ケースt_int: int param = boost::lexical_cast(param_strings[0]); switch (md.param_types[1]) {...} // 2 番目のパラメータ タイプ.. } 壊す; ケース n... }
これは、パラメーターと可能なタイプの数によって非常に急速に爆発します。(疑似コード)の行に沿った解決策を探しています:
for (auto& p : paramter_strings)
{
convert p to a variable of matching type (type id comes from meta_data).
store value
}
call function with stored values
つまり、関数呼び出しの分岐はありません。最小限の定型コードでこれを行うにはどうすればよいですか (任意の数のパラメーターをサポートする可能性があります)。これは、カスタム スクリプト言語へのバインドを作成することと考えることができます。