2012-02-12 79 views
1

我試圖將一個通用方法調用器(用於C++ OO/v8橋),使用可變參數模板元編程來構建參數列表,轉換爲本機類型,最後執行附加的方法,一旦進入PARAM列表是空的(並因此傳出內置):Variadic模板候選不匹配

template<typename... PARAMS> 
class InvocationBuilder { 
public: 

void invoke(const Arguments &source, PARAMS&... params) { 
    cout << "Invoke" << endl; 
    (instance->*(method))(*params...); 
} 

template<class HEAD, class ... TAIL> 
void invoke(const Arguments &source, PARAMS... params) { 
    cout << "Expand" << endl; 
    Type<HEAD> param(source[sizeof...(PARAMS)]); 
    InvocationBuilder<PARAMS..., HEAD> builder; 
    builder.template invoke<TAIL...>(source, params..., *param); 
} 

Type類僅僅是一個包裝來創建V8參數的堆棧作用域變體(以便,例如,可以使用字符*串而在調用期間的範圍內,但是一旦調用返回就自動清除)。

現在,當實際的橋樑調用此,有一個參數列表,使用:

InvocationBuilder<> builder; 
builder.template invoke<ARGS...>(args); 

哪裏ARGS是V8 ::參數參考。

編譯器正確鏈接參數生成的每一步,但無法匹配非模板化的invoke()方法,以實際執行本機C++方法。

錯誤消息是如下:

include/link/function.hh: In member function 'void sjs::link::InstanceFunctionVariadic<CLASS, ARGS>::InvocationBuilder<PARAMS>::invoke(const v8::Arguments&, PARAMS ...) [with HEAD = int, TAIL = {}, PARAMS = {int, int}, CLASS = SomeClass, ARGS = {int, int, int}]': 
include/link/function.hh:65:6: recursively instantiated from 'void sjs::link::InstanceFunctionVariadic<CLASS, ARGS>::InvocationBuilder<PARAMS>::invoke(const v8::Arguments&, PARAMS ...) [with HEAD = int, TAIL = {int}, PARAMS = {int}, CLASS = SomeClass, ARGS = {int, int, int}]' 
include/link/function.hh:65:6: instantiated from 'void sjs::link::InstanceFunctionVariadic<CLASS, ARGS>::InvocationBuilder<PARAMS>::invoke(const v8::Arguments&, PARAMS ...) [with HEAD = int, TAIL = {int, int}, PARAMS = {}, CLASS = SomeClass, ARGS = {int, int, int}]' 
include/link/function.hh:47:5: instantiated from 'v8::Handle<v8::Value> sjs::link::InstanceFunctionVariadic<CLASS, ARGS>::run(const v8::Arguments&) [with CLASS = SomeClass, ARGS = {int, int, int}]' 
test.cc:41:1: instantiated from here 
include/link/function.hh:65:6: error: no matching function for call to 'sjs::link::InstanceFunctionVariadic<SomeClass, int, int, int>::InvocationBuilder<int, int, int>::invoke(const v8::Arguments&, int&, int&, int)' 
include/link/function.hh:65:6: note: candidate is: 
include/link/function.hh:61:10: note: template<class HEAD, class ... TAIL> void sjs::link::InstanceFunctionVariadic<CLASS, ARGS>::InvocationBuilder::invoke(const v8::Arguments&, PARAMS ...) [with HEAD = HEAD, TAIL = {TAIL ...}, PARAMS = {int, int, int}, CLASS = SomeClass, ARGS = {int, int, int}] 

消息清楚地表明,前三個步驟,一個C++實例方法空隙測試(INT A,INT B,INT c)所示,工作正常,使用Type提取參數並傳遞結果 - 但我無法弄清楚爲什麼最終的invoke()沒有被正確地使用。我試圖完全專門化它,但後來我得到關於命名空間範圍(我假設是因爲該方法是模板類的成員)以外的專門化的錯誤消息。

我也嘗試轉移傳入/傳出參數列表,以便傳入是在類variadic模板中,而傳出的方法專門調用類的調用 - 但我碰到了「對不起,未實現「關於將可變參數解包到靜態模板中的消息。我也試過通過使用通用的單個可變參數模板,然後專門爲HEAD/TAIL案例,專門爲空集案例,但後來我得到立即含糊(可能因爲頭/尾值實際上並不作爲參數傳遞 - 僅在模板中)。

但到目前爲止,沒有骰子。任何人有任何其他想法,或可以解釋我要去哪裏錯了?

+1

不要混合模板和非模板重載。過載的解決方法非常棘手,可能無法實現您的想法。你可以叫一個人'invoke_impl'左右。 – 2012-02-12 14:12:15

+0

這個問題是我想要的方法是一個自動終止參數列表遞歸,而不是一個特定的額外情況。 我實際上嘗試了一個單獨的案例,使用sizeof ...(PARAMS)來確定列表是否構建,但這意味着調用方法會針對每個子階段構建,並且參數計數錯誤,因此會給出編譯錯誤。 – jka6510 2012-02-12 14:13:56

+0

對不起,我實際上沒有看到這個,所以我不應該說什麼。我看不出爲什麼你需要非靜態函數;通常這樣的助手類只使用靜態成員函數完成,因爲助手本身沒有並且不需要狀態。也許你是在混合責任太多,但我不可能告訴。我相信其他人將能夠提供一些實際有用的反饋。 – 2012-02-12 14:16:03

回答

1

需要注意的是:

  • 你明確地嘗試調用模板
  • 你的模板invoke總是需要PARAMS...作爲函數的參數傳遞

一個可能的選擇:

#include <functional> 

template<class... Types> struct List {}; 

template<class... PARAMS> struct Invoker { 
    typedef std::function<void (PARAMS&...)> Fn; 
    Fn fn_;  
    Invoker(const Fn&& fn) : fn_(fn) {} 

    void invoke(List<>, PARAMS&... params) { 
     fn_(params...); 
    } 

    template<class HEAD, class... TAIL, class... ARGS> 
    void invoke(List<HEAD, TAIL...>, ARGS... params) { 
     HEAD param; // or your Type<HEAD> ... etc. 
     invoke(List<TAIL...>(), params..., param); 
    } 
}; 

void f(int, int, int) {} // some function you want to call 

int main() { 
    Invoker<int,int,int> inv(&f); 
    inv.invoke(List<int,int,int>()); 
} 

...沒有你的用例的小型可編譯示例(帶有虛擬類型等),使它與你的代碼更緊密地匹配會花費一些時間。

+0

謝謝 - 是的,使用結構將可變參數模板參數與實際的方法參數聯繫起來,解決了我的問題,並且不再需要顯式模板化調用。 – jka6510 2012-02-12 16:28:31