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

これが本当に役立つ答えかどうかはわかりませんが、プリプロセッサを使用してかなりリスのようなことをすることができます:

#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欠点は、恐ろしいプリプロセッサのトリックと、まだfoo2か所で対処しなければならないという事実です。

于 2012-04-09T17:15:27.653 に答える
1

テンプレートメタプログラミングを使用して、ある種の関数を自動的に検出できます。たとえば、タイプTが与えられた場合、「Tにはoperator+?」という質問にプログラムで答えることができます。しかし、一般的なケースでは、上記で行っていることをその言語で自動的に行うことはできません。

于 2012-04-09T15:36:03.527 に答える