3

我正在用 C++ 开发一种脚本语言,它使用解释器中“内置”的函数。我正在使用以下构造将函数名称映射到它们各自的指针:

typedef void(*BuiltInFunction)(Context*);
typedef std::unordered_map<std::string, BuiltInFunction> BuiltinFunctionsMap;

Context自定义类在哪里。

然后我有这样的函数声明:

namespace BuiltIns {
    void _f_print(Context* context);
    void _f_error(Context* context);
    void _f_readline(Context* context);
    void _f_read(Context* context);
    void _f_readchar(Context* context);
    void _f_eof(Context* context);
    ...
}

最后是一个用实际指针填充地图的例程:

BuiltinFunctionsMap BuiltIns::populateFunctions() {
    BuiltinFunctionsMap funcMap;
    // Standard I/0
    funcMap["print"] = &BuiltIns::_f_print;
    funcMap["error"] = &BuiltIns::_f_error;
    funcMap["readline"] = &BuiltIns::_f_readline;
    funcMap["read"] = &BuiltIns::_f_read;
    funcMap["readchar"] = &BuiltIns::_f_readchar;
    funcMap["eof"] = &BuiltIns::_f_eof;
    ...
    return funcMap;
}

我要问的是是否有一种方法可以使用模板或类似的东西从函数声明中自动生成填充函数。目前,我正在使用正则表达式,这很简单,但是每当我添加新函数时我都必须这样做,而且很麻烦。

4

2 回答 2

1

您可以使用模板元编程自动检测某些类型的函数——例如,给定类型 T,您可以以编程方式回答问题“T 有operator+吗?”。但在一般情况下,您无法使用该语言自动执行上述操作。

于 2012-04-09T15:36:03.527 回答
1

我不知道这是否真的是一个有用的答案,但你可以使用预处理器做一些非常松鼠的事情

#include <iostream>
#include <map>
#include <string>

class Context {}; 
typedef void (*BuiltInFunction)(Context*);

// a list of your function names
#define FN_NAMES \
X(foo)  \
X(bar)  \
X(baz)

// this declares your functions (you also have to define them 
// somewhere else, e.g. below or in another file)
#define X(a) void _f_ ## a ## _print(Context *context);
namespace BuiltIns {
  FN_NAMES
}
#undef X

// a global map initialized (using C++11's initializer syntax)
// to strings mapped to functions
#define X(a) {#a, &BuiltIns::_f_ ## a ## _print},
std::map<std::string, BuiltInFunction> g_fns = { 
  FN_NAMES
};
#undef X

int main() {
  g_fns["foo"](NULL);  // calls BuiltIns::_f_foo_print(NULL) 
}

// (these have to be defined somewhere)
namespace BuiltIns {
  void _f_foo_print(Context *context) {
    std::cout << "foo\n";
  }
  void _f_bar_print(Context *context) {
    std::cout << "bar\n";
  }
  void _f_baz_print(Context *context) {
    std::cout << "baz\n";
  }
}

这种方法具有自动生成例如字符串"foo"并将其绑定到_f_foo_print函数的好处。foo缺点是可怕的预处理器诡计以及您仍然必须在两个地方处理的事实。

于 2012-04-09T17:15:27.653 回答