2016-10-23 8 views
2

私は1つの引数を取る関数に関数をラップしようとしています(状態インタープリタ)。私が関数を直接渡すと、すべて正常に動作します。 しかし、私が追加の関数をラップすると、コンパイラエラーが発生します。 説明してください、私は間違って何をしています。テンプレート関数ラッパー

#include <iostream> 

template <std::size_t... Is> 
struct _indices { 
    template <template <size_t...> class Receiver> 
    using Relay = Receiver<Is...>; 
}; 

template <std::size_t N, std::size_t... Is> 
struct _indices_builder : _indices_builder<N-1, N-1, Is...> {}; 

template <std::size_t... Is> 
struct _indices_builder<0, Is...> { 
    using type = _indices<Is...>; 
}; 

struct lua_State 
{}; 

template <typename Ret, typename... Args> 
struct FunctionWrapperImpl { 
    template <size_t... Indices> 
    struct ImplementationNonVoid { 
     template <Ret (* func)(Args...)> static inline 
     int invoke(lua_State* state) { 
      func(10); 
      return 1; 
     } 
    }; 

    using Implementation = 
     typename _indices_builder<sizeof...(Args)>::type::template Relay< 
      ImplementationNonVoid 
     >; 
}; 

template <typename ToBeWrapped> 
struct Wrapper { 
}; 

template <typename Ret, typename... Args> 
struct Wrapper<Ret (*)(Args...)>: 
    FunctionWrapperImpl<Ret, Args...>::Implementation {}; 


int test(int a) 
{ 
    std::cout<< a; 
    return 5; 
} 


typedef int (*lua_CFunction) (lua_State *L); 

template <typename T> 
lua_CFunction register_func(T fun) 
{ 
    lua_CFunction f = 
      (&Wrapper<decltype (fun)>::template invoke<T>); // Error 
       // no matches converting function 'invoke' to type 'lua_CFunction {aka int (*)(struct lua_State*)}' 
    //do somthing with f                  
    return f; 
} 

int main(int argc, char *argv[]) 
{ 
    lua_State s; 

    lua_CFunction t = (&Wrapper<decltype(&test)>::template invoke<&test>); // work 
    t(&s); // no problem 
    lua_CFunction t2 = register_func(&test); 
    t2(&s); 

    return 0; 
} 

完全なコンパイルエラー。

main.cpp: In instantiation of 'int (* register_func(T))(lua_State*) [with T = int (*)(int); lua_CFunction = int (*)(lua_State*)]': 
main.cpp:69:40: required from here 
main.cpp:58:65: error: no matches converting function 'invoke' to type 'lua_CFunction {aka int (*)(struct lua_State*)}' 
    lua_CFunction f = (&Wrapper<decltype (fun)>::template invoke<T>); 
                   ^
main.cpp:25:7: note: candidate is: template<int (* func)(int)> static int FunctionWrapperImpl<Ret, Args>::ImplementationNonVoid<Indices>::invoke(lua_State*) [with Ret (* func)(Args ...) = func; long unsigned int ...Indices = {0ul}; Ret = int; Args = {int}] 
    int invoke(lua_State* state) { 

答えて

1

の間に有意な差があります:明らかにあなたは後者を渡す機能のタイプであるあなたがTを使用する旧における

(&Wrapper<decltype (fun)>::template invoke<T>); 

(&Wrapper<decltype(&test)>::template invoke<&test>); 

はあなた呼び出し方法に対して関数へのポインタを指定してください。 invokeメソッドは、型のないテンプレートパラメータ、ここでは関数ポインタを受け付けるため、2番目のコードは正しくコンパイルされます。覚えておいてください。タイプテンプレートパラメータとテンプレートテンプレートパラメータを混在させることができないように、非タイプテンプレートパラメータとタイプテンプレートパラメータを混在させることはできません。

+0

ありがとうございます。一つの小さな質問。 Wrapperの周りにラッパー関数を記述することは可能ですか? – a1ien

+0

@ a1ienさて、関数型から離れて、作成したラッパーに 'invoke'メソッドの中で呼び出す関数へのポインタを直接渡すこともできますが、実際の必要性に依存します。 –

+0

I lua_CFunctionのregister_func(RET(* FUNC)(Argsの...)) { \t lua_CFunctionのF = \t \t \t(&ラッパー<型名のRet、型名... Argsの>このテンプレートを試してみてください::テンプレートはを呼び出す); \t return f; } – a1ien

関連する問題