fork download
  1. #include <iostream>
  2. #include <tuple>
  3. #include <type_traits>
  4. using namespace std;
  5.  
  6.  
  7. //* External type stubs
  8. struct lua_State;
  9. void* lua_touserdata(lua_State *, int) { return nullptr; }
  10. int lua_upvalueindex(int) { return 0; }
  11. int luaL_error(lua_State *, const char *) { return 0; }
  12. struct Lua
  13. {
  14. lua_State *L;
  15. template <typename T>
  16. T* CheckPtr(int) { return nullptr; }
  17. template <int, typename ...Args>
  18. tuple<Args...> CheckArgs() { return {}; }
  19. template <typename T>
  20. void Push(T) {}
  21. };
  22. //*/
  23.  
  24. template <typename F>
  25. class FunctionPointer
  26. {
  27. template <typename R, typename ...Args>
  28. static R func_return( R(*)(Args...) )
  29. { return {}; }
  30. using R_ = decltype( func_return( (F)nullptr ) );
  31. struct void_type {};
  32.  
  33. public:
  34. F f;
  35. using R = typename conditional<is_void<R_>::value, void_type, R_>::type;
  36. template <typename ...Args>
  37. R Apply(tuple<Args...> &args)
  38. {
  39. cout << __PRETTY_FUNCTION__ << '\n';
  40. return {};
  41. }
  42. };
  43.  
  44.  
  45. template<typename R, typename ...Args>
  46. struct Wrapper
  47. {
  48. using F = R (*)(Args...);
  49.  
  50. static int f (lua_State *L, F f)
  51. {
  52. Lua lua {L};
  53.  
  54. // Build a tuple of arguments.
  55. auto args = lua.CheckArgs<1, Args...>();
  56.  
  57. // Grab the function pointer.
  58. FunctionPointer<F> fp {f};
  59. // Apply the function to the tuple.
  60. if (is_void<R>::value)
  61. {
  62. fp.Apply(args);
  63. return 0;
  64. }
  65. else
  66. {
  67. lua.Push( fp.Apply(args) );
  68. return 1;
  69. }
  70. }
  71. };
  72.  
  73.  
  74. void func1(int) {}
  75. lua_State* func2(Lua) { return nullptr; }
  76.  
  77. int main()
  78. {
  79. Wrapper<void, int> w1;
  80. w1.f(nullptr, &func1);
  81.  
  82. Wrapper<lua_State*, Lua> w2;
  83. w2.f(nullptr, &func2);
  84. }
  85.  
Success #stdin #stdout 0s 3140KB
stdin
Standard input is empty
stdout
FunctionPointer<F>::R FunctionPointer<F>::Apply(std::tuple<_Args1 ...>&) [with Args = {int}; F = void (*)(int); FunctionPointer<F>::R = FunctionPointer<void (*)(int)>::void_type]
FunctionPointer<F>::R FunctionPointer<F>::Apply(std::tuple<_Args1 ...>&) [with Args = {Lua}; F = lua_State* (*)(Lua); FunctionPointer<F>::R = lua_State*]