2012-02-12 24 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クラスは単に、例えば、CHAR *文字列を使用することができるようにV8パラメータ(のスタックスコープバリアントを作成するためのラッパーです呼び出し中は範囲内にありますが、呼び出しが戻ったら自動的にクリーンアップされます)。

さて、実際のブリッジが使用して、パラメータリストで、これを呼び出すとき:

引数はV8 ::引数の参照である
InvocationBuilder<> builder; 
builder.template invoke<ARGS...>(args); 

を。

コンパイラは、パラメータ生成の各ステップを正しくチェーンしますが、テンプレート化されていない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}] 

メッセージが明らかに最初の3つのステップは、C++インスタンスメソッドボイド試験(int型、int型B、int型C)のため、正しく動作していることを示していますTypeを使用してパラメータを抽出して結果を渡しますが、最終的なinvoke()が正しく使用されていない理由を理解できません。

私は完全に専門化しようとしましたが、名前空間スコープの外で特殊化に関するエラーメッセージが表示されます(これは、メソッドがテンプレート化されたクラスのメンバーであるためです)。

私は着信がクラスのバリデーショナルなテンプレートに入っているように着信/発信のパラメータリストをシフトしようとしました。代わりに呼び出しのためにクラスを特化する方法で発信していますが、 varimicを静的テンプレートに展開する方法については「実装されていません」というメッセージが表示されます。

また、HEAD/TAILの場合に特化し、空のセットケースに特化した一般的な単一可変テンプレートを使用して解決しようとしましたが、ただちにあいまいさがあります(HEAD/TAIL値は実際にはパラメータとして渡されません - 単にテンプレートに渡されます)。

これまでのところ、サイコロはありません。誰でも他のアイディアを持っているか、どこに間違っているのか説明できますか?

+1

テンプレートオーバーロードとテンプレートオーバーロードを混在させないでください。オーバーロードの解決は難しく、あなたが考えることをしないかもしれません。あなたは1人の人間に 'invoke_impl'などと呼ぶことができます。 –

+0

この問題は、メソッドが特定の追加の場合ではなく、パラメータリストの再帰を自動的に終了させたいということです。 実際にはsizeof ...(PARAMS)を使用してリストが構築されているかどうかを確認していますが、呼び出しメソッドが誤ったパラメータ数でサブステージごとに構築されていることを意味します。エラーをコンパイルします。 – jka6510

+0

申し訳ありませんが、私は実際にこれを見ていないので、何も言ってはいけません。なぜ非静的関数が必要なのかわかりません。典型的には、そのようなヘルパークラスは、ヘルパー自体が状態を必要とせず、状態を必要としないので、静的メンバ関数のみで行われる。おそらくあなたは責任を混同しすぎているかもしれませんが、私が言うことは不可能です。誰かが実際に役に立つフィードバックを提供できると確信しています。 –

答えて

1

こと注:

#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>()); 
} 
:あなたが明示的にあなたのテンプレート invokeは常に関数の引数が

一つの可能​​な代替として渡すことがPARAMS...を必要とテンプレート

  • を起動しようとする

    • ...なしあなたのユースケース(コンパイル可能なダミー型など)の小さなコンパイル可能な例では、これをあなたのコードに近づけるには少し時間がかかります。

  • +0

    ありがとう、構造体を使用してバリデーショナルなテンプレートパラメータを実際のメソッドparamに関連付けることで、私の問題を解決し、呼び出しを明示的にテンプレート化する必要性を排除しました。 – jka6510

    関連する問題