2016-10-23 4 views
2

Ich versuche, jede Funktion in eine Funktion, die ein Argument (State Interpreter) dauert, zu wickeln. Und wenn ich die Funktion direkt übergebe, funktioniert alles gut. Aber wenn ich in eine zusätzliche Funktion einbinden, bekomme ich einen Compilerfehler. Erklären Sie bitte, was mache ich falsch.Template-Funktion Wrapper

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

Vollständiger Kompilierungsfehler.

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) { 

Antwort

1

Es gibt signifikanten Unterschied zwischen:

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

und

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

in der ehemaligen Sie T verwenden, die offensichtlich die Typ der Funktion, die Sie in der zweiten passieren ist, dass Sie Stellen Sie den Zeiger auf die Funktion zur Aufrufmethode bereit. Als invoke Methode akzeptiert nicht-type Vorlage Parameter, hier Funktionszeiger, der zweite Code kompiliert korrekt. Denken Sie daran - Sie können nicht-type Template-Parameter nicht mit type template-Parametern mischen, genauso wie Sie type template-Parameter nicht mit template template-Parametern mischen können.

+0

Danke für die Erklärung. Eine kleine Frage. Ist es möglich, eine Wrapper-Funktion um den Wrapper zu schreiben, und wenn ja, wie? – a1ien

+0

@ a1ien Nun, eine Lösung könnte sein, zu dem erstellten Wrapper neben dem Funktionstyp direkt einen Zeiger auf die Funktion zu übergeben, die Sie in der 'invoke'-Methode aufrufen möchten, aber es hängt wirklich von Ihren tatsächlichen Bedürfnissen ab ... –

+0

I versuchen Sie diese Vorlage lua_CFunction register_func (Ret (* func) (Args ...)) { \t lua_CFunction f = \t \t \t (& Wrapper :: Vorlage aufrufen ); \t Rückgabe f; } – a1ien