2012-04-09 36 views
3

我正在C++中開發一個腳本語言,它使用解釋器中「內置」功能。我使用下面的施工函數名稱映射到它們各自的指針:帶功能指針的std :: map自動填充

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; 
} 

我所問的是,如果有辦法使用模板或類似的東西從函數聲明中自動生成填充函數。目前,我使用的正則表達式很簡單,但每當添加新的函數時都必須這樣做,而且很麻煩。

+3

我對C++相當陌生。我會很樂意考慮更好的解決方案:) – Tibor 2012-04-09 15:22:21

+0

'std :: function'是你的朋友。它可以是一個函數指針或函數對象,這意味着它可以是很多很多的東西。函數指針是非常嚴格的,而'std :: function'允許很多自由度。 – Puppy 2012-04-09 15:33:37

+0

如果你可以用正則表達式來做到這一點,你不能把它作爲構建過程中的一個步驟嗎? – alexisdm 2012-04-09 15:35:41

回答

1

我不知道這是不是真的有幫助的答案,但是你可以使用預處理程序做一些pretty squirrelly stuff

#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

1

可以自動檢測一些種例如使用模板metaprogramming-功能,給定一個類型T,你可以通過編程回答「是否T的一個operator+?」。但在一般情況下,您無法在語言中自動執行以上操作。