假设我有一些反射元数据,其中包含以下信息:
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;
我想在这个地图中调用函数,给定函数名称和参数都为 strings 。我的问题不是转换参数(例如使用boost::lexical_cast
),而是转换为正确类型的函数指针并调用函数。如果我允许8种类型和最多8种参数,那我的代码中已经有很多分支。我想避免的(伪代码):
switch (md.param_types.size()) { case 0: cast function pointer, call it break; case 1: switch (md.param_types[0]) { case t_int: int param = boost::lexical_cast(param_strings[0]); cast function pointer, call with param case ... } break; case 2: switch (md.param_types[0]) { case t_int: int param = boost::lexical_cast(param_strings[0]); switch (md.param_types[1]) {...} // second param type.. } break; case 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
即。没有函数调用的分支。如何使用最少量的样板代码(可能支持任意数量的参数)来完成此操作?您可以将此视为创建自定义脚本语言的绑定。
答案 0 :(得分:0)
我提出了一种方法。
假设你有一个unsigned int V的向量,你就知道了 向量的每个元素都是非负数 它小于N(或者说,例如20)。 以下是您要将矢量V更改为a的内容 正整数:
n = sequence_to_code(V,N); // or n = encode(V,20U);
这是代码。
long sequence_to_long(const std::vector<unsigned int> & L,
unsigned long n) {
long result = 0L;
std::vector<unsigned int>::const_iterator w=L.begin(),e=L.end();
if(w!=e) {
result += (*w)+1;
unsigned long the_pow = n;
unsigned int i = 1U;
++w;
while(w!=e) {
result += (*w+1)*(the_pow);
++w;++i;the_pow *= n;
}
}
return result;
}
实际上,我可能应该返回“unsigned long”。
此外,您可以将同一例程与创建的程序一起使用 一个文本文件。该文本文件将包含C ++代码。假设你创建了 “the_defines.hpp”。我将举例说明......
例如,假设我们有t_int = 0; t_double = 1,d_str = 2 而且只有三种类型。 然后“the_define.hpp”可以是文件:
#define TYPE_EMPTY 0U
#define TYPE_INT 1U
#define TYPE_DOUBLE 2U
#define TYPE_STR 3U
#define TYPE_INT_INT 4U
#define TYPE_DOUBLE_INT 5U
然后可以在下面使用此代码 方式:
std::vector<unsigned int> L;
// add entries to L
long n = sequence_to_long(L,3UL);
switch(n) {
case TYPE_INT:
std::cout << "an integer\n";
break;
case TYPE_INT_DOUBLE:
std::cout << "two args; first is an int; second is a double\n:
break;
}
当然,您可以创建一个包含非常代码的文本文件 长枚举(如果你想避免#define)。例如,
enum class extended_type {
type_int,
type_double,
type_str,
type_int_int,
type double_int,
等等。
您还可以编写一个创建(一个或多个)文本文件的程序。 这些文本文件也可以通过C ++代码实现。例如,您创建的文件 可能是:
swtich(n) {
case empty:
FILLIN
break;
case t_int:
FILLIN
break;
等等,直到
case t_str_str:
FILLIN;
break;
}
我还建议使用内联函数或常规函数进行投射 功能。例如,
inline int inside_int(foo f) {
const bar & b = * reinterpret_cast<const bar *>(f.pointer());
return b.d_x;
}
我建议这是因为DRY(不要重复自己)和存在 能够搜索该函数的所有实例。
我知道这些程序不处理错误(溢出, 零指针等。)
标记