fork download
  1. #include <iostream>
  2. #include <functional>
  3. #include <tuple>
  4. #include <type_traits>
  5. #include <vector>
  6. using namespace std;
  7.  
  8. #include <functional>
  9. #include <tuple>
  10. #include <type_traits>
  11. using namespace std;
  12.  
  13. #include <stdio.h>
  14. #include <string.h>
  15.  
  16. template<typename T, typename U, std::enable_if_t<std::is_same<T, U>::value, int> = 0>
  17. T convert_type(U _in)
  18. {
  19. //return const_cast<U>(_in);
  20. return _in;
  21. }
  22.  
  23. template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
  24. T convert_type(U _in)
  25. {
  26. //return const_cast<U>(_in);
  27. return _in;
  28. }
  29.  
  30.  
  31. // these conversion functions only can convert type to pointer to type, else return reference to type, so they're a bit limited
  32. // pointer to pointer, or
  33. template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
  34. T& convert_type(U& _in)
  35. {
  36. return _in;
  37. }
  38.  
  39. template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_lvalue_reference_t<U>>::value, int> = 0>
  40. T& convert_type(U& _in)
  41. {
  42. return _in;
  43. }
  44.  
  45. template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_lvalue_reference_t<std::add_const_t<U>>>::value, int> = 0>
  46. T& convert_type(U& _in)
  47. {
  48. return _in;
  49. }
  50.  
  51.  
  52. // for conversion to pointer
  53. //T&* to T*
  54. template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_pointer_t<U>>::value, int> = 0>
  55. T convert_type(U& _in)
  56. {
  57. return std::addressof(_in);
  58. }
  59.  
  60. template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
  61. T convert_type(U& _in)
  62. {
  63. return std::addressof(_in);
  64. }
  65.  
  66. template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_pointer_t<std::add_const_t<U>>>::value, int> = 0>
  67. T convert_type(U& _in)
  68. {
  69. return std::addressof(_in);
  70. }
  71.  
  72. template<typename T>
  73. struct function_traits;
  74.  
  75. template<typename R, typename ...Args>
  76. struct function_traits<std::function<R(Args...)>>
  77. {
  78. static const size_t nargs = sizeof...(Args);
  79.  
  80. typedef R result_type;
  81.  
  82. template <size_t i>
  83. struct arg
  84. {
  85. typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
  86. };
  87.  
  88. static const bool isGlobalOrStaticContainer = true;
  89. static const bool isClassContainer = false;
  90. static const bool isPointerContainer = false;
  91. static const bool isConstInClassContainer = false;
  92. static const bool returnsVoid = std::is_same<R, void>::value;
  93. };
  94.  
  95. template<typename C, typename R, typename ...Args>
  96. struct function_traits<std::function<R(*C::*)(Args...)>>
  97. {
  98. static const size_t nargs = sizeof...(Args);
  99.  
  100. typedef R result_type;
  101.  
  102. template <size_t i>
  103. struct arg
  104. {
  105. typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
  106. };
  107.  
  108. static const bool isGlobalOrStaticContainer = false;
  109. static const bool isClassContainer = false;
  110. static const bool isPointerContainer = true;
  111. static const bool isConstInClassContainer = false;
  112. static const bool returnsVoid = std::is_same<R, void>::value;
  113. };
  114.  
  115. template<typename C, typename R, typename ...Args>
  116. struct function_traits<std::function<R(C::*)(Args...)>>
  117. {
  118. static const size_t nargs = sizeof...(Args);
  119.  
  120. typedef R result_type;
  121.  
  122. template <size_t i>
  123. struct arg
  124. {
  125. typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
  126. };
  127.  
  128. static const bool isGlobalOrStaticContainer = false;
  129. static const bool isClassContainer = true;
  130. static const bool isPointerContainer = false;
  131. static const bool isConstInClassContainer = false;
  132. static const bool returnsVoid = std::is_same<R, void>::value;
  133. };
  134.  
  135. template<typename C, typename R, typename ...Args>
  136. struct function_traits<std::function<R(C::*)(Args...) const>>
  137. {
  138. static const size_t nargs = sizeof...(Args);
  139.  
  140. typedef R result_type;
  141.  
  142. template <size_t i>
  143. struct arg
  144. {
  145. typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
  146. };
  147.  
  148. static const bool isGlobalOrStaticContainer = false;
  149. static const bool isClassContainer = true;
  150. static const bool isPointerContainer = false;
  151. static const bool isConstInClassContainer = true;
  152. static const bool returnsVoid = std::is_same<R, void>::value;
  153. };
  154.  
  155. template<typename ParamType> class Param
  156. {
  157. public:
  158.  
  159. typedef ParamType Type;
  160.  
  161. static const bool isOut = false;
  162. };
  163.  
  164. template<typename ParamType> class ParamOut : public Param<ParamType>
  165. {
  166. public:
  167.  
  168. static const bool isOut = true;
  169. };
  170.  
  171. template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename ParamType, size_t paramIndex, typename... ParamTypes>
  172. static bool UnwrapParameter(unsigned argc, std::vector<void*>& args, typename ParamType::Type &ppt)
  173. {
  174. if (argc > paramIndex)
  175. {
  176. ppt = *((std::add_pointer_t<typename ParamType::Type>(args[paramIndex])));
  177. }
  178.  
  179. return true;
  180. }
  181.  
  182. template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename... ParamType, size_t... paramIndex>
  183. static bool UnwrapParameters(unsigned argc, std::vector<void*>& args, std::tuple<typename ParamType::Type...>& params, std::index_sequence<paramIndex...>)
  184. {
  185. bool r[] = { true, UnwrapParameter<Type, ReturnType, MethodType, Method, ParamType, paramIndex, ParamType...>(argc, args, std::get<paramIndex>(params))... };
  186.  
  187. bool res = true;
  188. for (size_t i = 0; i < sizeof...(ParamType) + 1 && res == true; i++)
  189. res &= r[i];
  190. return res;
  191. }
  192.  
  193. template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename... ParamType>
  194. static bool UnwrapParameters(unsigned argc, std::vector<void*>& args, std::tuple<typename ParamType::Type...>& params)
  195. {
  196. return UnwrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params, std::make_index_sequence<sizeof...(ParamType)>{});
  197. }
  198.  
  199.  
  200. template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename ParamType, size_t paramIndex, typename... ParamTypes>
  201. static bool WrapParameter(unsigned argc, std::vector<void*>& args, typename ParamType::Type &ppt)
  202. {
  203. if (ParamType::isOut && (argc > paramIndex))
  204. {
  205. // Wrap them back - nothing to do here, in this example
  206. }
  207.  
  208. return true;
  209. }
  210.  
  211. template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename... ParamType, size_t... paramIndex>
  212. static bool WrapParameters(unsigned argc, std::vector<void*>& args, std::tuple<typename ParamType::Type...>& params, std::index_sequence<paramIndex...>)
  213. {
  214. bool r[] = { true, WrapParameter<Type, ReturnType, MethodType, Method, ParamType, paramIndex, ParamType...>(argc, args, std::get<paramIndex>(params))... };
  215.  
  216. bool res = true;
  217. for (size_t i = 0; i < sizeof...(ParamType)+1 && res == true; i++)
  218. res &= r[i];
  219. return res;
  220. }
  221.  
  222. template<typename Type, typename ReturnType, typename MethodType, MethodType Method, typename... ParamType>
  223. static bool WrapParameters(unsigned argc, std::vector<void*>& args, std::tuple<typename ParamType::Type...>& params)
  224. {
  225. return WrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params, std::make_index_sequence<sizeof...(ParamType)>{});
  226. }
  227.  
  228.  
  229. template<typename Type, typename ReturnType, typename MethodType,
  230. typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::isPointerContainer, MethodType>::type Method,
  231. typename... ParamType, size_t... paramIndex>
  232. static ReturnType CallMethodRet(bool& success, Type* obj, std::tuple<typename ParamType::Type...>& params, std::index_sequence<paramIndex...>)
  233. {
  234. if (!(obj && (obj->*Method)))
  235. success = false;
  236.  
  237. return (obj->*Method)(convert_type<typename function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::template arg<paramIndex>::type, typename ParamType::Type>(std::get<paramIndex>(params))...);
  238. }
  239.  
  240. template<typename Type, typename ReturnType, typename MethodType,
  241. typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::isGlobalOrStaticContainer, MethodType>::type Method,
  242. typename... ParamType, size_t... paramIndex>
  243. static ReturnType CallMethodRet(bool& success, Type* obj, std::tuple<typename ParamType::Type...>& params, std::index_sequence<paramIndex...>)
  244. {
  245. if (!(*Method))
  246. success = false;
  247.  
  248. return (*Method)(convert_type<typename function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::template arg<paramIndex>::type, typename ParamType::Type>(std::get<paramIndex>(params))...);
  249. }
  250.  
  251. template<typename Type, typename ReturnType, typename MethodType,
  252. typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::isClassContainer, MethodType>::type Method,
  253. typename... ParamType, size_t... paramIndex>
  254. static ReturnType CallMethodRet(bool& success, Type* obj, std::tuple<typename ParamType::Type...>& params, std::index_sequence<paramIndex...>)
  255. {
  256. if (!(obj && (Method)))
  257. success = false;
  258.  
  259. return (obj->*Method)(convert_type<typename function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::template arg<paramIndex>::type, typename ParamType::Type>(std::get<paramIndex>(params))...);
  260. }
  261.  
  262. template <typename Type, typename ReturnType, typename MethodType, MethodType Method, typename... ParamType>
  263. static ReturnType CallMethodRet(bool& success, Type* obj, std::tuple<typename ParamType::Type...>& params)
  264. {
  265. return CallMethodRet<Type, ReturnType, MethodType, Method, ParamType...>(success, obj, params, std::make_index_sequence<sizeof...(ParamType)>{});
  266. }
  267.  
  268.  
  269. template<typename Type, typename ReturnType, typename MethodType,
  270. typename std::enable_if<!function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::returnsVoid, MethodType>::type Method,
  271. typename... ParamType>
  272. static bool ExecuteMethod(Type* obj, unsigned argc, std::vector<void*>& args, ReturnType& result)
  273. {
  274. try
  275. {
  276. const unsigned numArgs = sizeof...(ParamType);
  277.  
  278. std::tuple<typename ParamType::Type...> params = std::make_tuple(typename ParamType::Type()...);
  279.  
  280. if (!UnwrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params))
  281. return false;
  282.  
  283. bool success = true;
  284.  
  285. result = CallMethodRet<Type, ReturnType, MethodType, Method, ParamType...>(success, obj, params);
  286.  
  287. if (!success)
  288. return false; // Throw method not found here
  289.  
  290. if (!WrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params))
  291. return false;
  292. }
  293. catch (...)
  294. {
  295. // whatever...
  296. }
  297.  
  298. return true;
  299. }
  300.  
  301. template<typename Type, typename ReturnType, typename MethodType,
  302. typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::returnsVoid, MethodType>::type Method,
  303. typename... ParamType>
  304. static bool ExecuteMethod(Type* obj, unsigned argc, std::vector<void*>& args)
  305. {
  306. try
  307. {
  308. const unsigned numArgs = sizeof...(ParamType);
  309.  
  310. std::tuple<typename ParamType::Type...> params = std::make_tuple(typename ParamType::Type()...);
  311.  
  312. if (!UnwrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params))
  313. return false;
  314.  
  315. bool success = true;
  316.  
  317. CallMethodRet<Type, ReturnType, MethodType, Method, ParamType...>(success, obj, params);
  318.  
  319. if (!success)
  320. return false; // Throw method not found here
  321.  
  322. if (!WrapParameters<Type, ReturnType, MethodType, Method, ParamType...>(argc, args, params))
  323. return false;
  324. }
  325. catch (...)
  326. {
  327. // whatever...
  328. }
  329. return true;
  330. }
  331.  
  332. class O
  333. {
  334. public:
  335. void func(int a, string b, bool& c, const char* d)
  336. {
  337. std::cout << "Successfully called func with in values " << a << "," << b << "," << c << " and " << d << std::endl;
  338.  
  339. c = true;
  340.  
  341. std::cout << "Successfully called func with out values " << a << "," << b << "," << c << " and " << d << std::endl;
  342. }
  343.  
  344. int func_i(int a, string b, bool& c, const char* d)
  345. {
  346. std::cout << "Successfully called func with in values " << a << "," << b << "," << c << " and " << d << std::endl;
  347.  
  348. c = false;
  349.  
  350. std::cout << "Successfully called func with out values " << a << "," << b << "," << c << " and " << d << std::endl;
  351.  
  352. return 1;
  353. }
  354. };
  355.  
  356. int main() {
  357.  
  358. int a = 1;
  359. string b = "string";
  360. bool c = false;
  361. char* d = new char[sizeof "char*"];
  362. strcpy(d, "char*");
  363.  
  364. std::vector<void*> v {(void*)&a, (void*)&b, (void*)&c, (void*)&d};
  365.  
  366. std::cout << std::endl;
  367.  
  368. O o;
  369.  
  370. std::cout << ExecuteMethod<O, void, void(O::*)(int, string, bool&, const char*), &O::func, Param<int>, Param<string>, ParamOut<bool>, Param<char*>>(&o, v.size(), v); // with Param<const char*> is compiling, but I need to pass Param<char*>
  371.  
  372. std::cout << std::endl << std::endl;
  373.  
  374. int result = 0;
  375. std::cout << ExecuteMethod<O, int, int(O::*)(int, string, bool&, const char*), &O::func_i, Param<int>, Param<string>, ParamOut<bool>, Param<char*>>(&o, v.size(), v, result) << std::endl; // with Param<const char*> is compiling Param<char*>
  376. std::cout << result << std::endl;
  377.  
  378. delete[] d;
  379.  
  380. return 0;
  381. }
Compilation error #stdin compilation error #stdout 0s 3416KB
stdin
Standard input is empty
compilation info
prog.cpp: In instantiation of 'ReturnType CallMethodRet(bool&, Type*, std::tuple<typename ParamType::Type ...>&, std::index_sequence<paramIndex ...>) [with Type = O; ReturnType = void; MethodType = void (O::*)(int, std::basic_string<char>, bool&, const char*); typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type> >::isClassContainer, MethodType>::type Method = &O::func; ParamType = Param<int>, Param<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ParamOut<bool>, Param<char*>; unsigned int ...paramIndex = 0u, 1u, 2u, 3u; std::index_sequence<paramIndex ...> = std::integer_sequence<unsigned int, 0u, 1u, 2u, 3u>]':
prog.cpp:265:77:   required from 'ReturnType CallMethodRet(bool&, Type*, std::tuple<typename ParamType::Type ...>&) [with Type = O; ReturnType = void; MethodType = void (O::*)(int, std::basic_string<char>, bool&, const char*); MethodType Method = &O::func; ParamType = {Param<int>, Param<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ParamOut<bool>, Param<char*>}]'
prog.cpp:317:74:   required from 'bool ExecuteMethod(Type*, unsigned int, std::vector<void*>&) [with Type = O; ReturnType = void; MethodType = void (O::*)(int, std::basic_string<char>, bool&, const char*); typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type> >::returnsVoid, MethodType>::type Method = &O::func; ParamType = {Param<int>, Param<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ParamOut<bool>, Param<char*>}]'
prog.cpp:370:168:   required from here
prog.cpp:259:186: error: no matching function for call to 'convert_type(char*&)'
     return (obj->*Method)(convert_type<typename function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::template arg<paramIndex>::type, typename ParamType::Type>(std::get<paramIndex>(params))...);
                                                                                                                                                                                          ^
prog.cpp:17:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same< <template-parameter-1-1>, <template-parameter-1-2> >::value, int>::type <anonymous> > T convert_type(U)
 T convert_type(U _in)
   ^
prog.cpp:17:3: note:   template argument deduction/substitution failed:
prog.cpp:16:85: error: no type named 'type' in 'struct std::enable_if<false, int>'
 template<typename T, typename U, std::enable_if_t<std::is_same<T, U>::value, int> = 0>
                                                                                     ^
prog.cpp:16:85: note: invalid template non-type parameter
prog.cpp:24:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_const<U>::type>::value, int>::type <anonymous> > T convert_type(U)
 T convert_type(U _in)
   ^
prog.cpp:24:3: note:   template argument deduction/substitution failed:
prog.cpp:23:103: error: no type named 'type' in 'struct std::enable_if<false, int>'
 template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
                                                                                                       ^
prog.cpp:23:103: note: invalid template non-type parameter
prog.cpp:34:4: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_const<U>::type>::value, int>::type <anonymous> > T& convert_type(U&)
 T& convert_type(U& _in)
    ^
prog.cpp:34:4: note:   template argument deduction/substitution failed:
prog.cpp:33:103: error: no type named 'type' in 'struct std::enable_if<false, int>'
 template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
                                                                                                       ^
prog.cpp:33:103: note: invalid template non-type parameter
prog.cpp:40:4: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_lvalue_reference<U>::type>::value, int>::type <anonymous> > T& convert_type(U&)
 T& convert_type(U& _in)
    ^
prog.cpp:40:4: note:   template argument deduction/substitution failed:
prog.cpp:39:114: error: no type named 'type' in 'struct std::enable_if<false, int>'
 template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_lvalue_reference_t<U>>::value, int> = 0>
                                                                                                                  ^
prog.cpp:39:114: note: invalid template non-type parameter
prog.cpp:46:4: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_lvalue_reference<typename std::add_const<U>::type>::type>::value, int>::type <anonymous> > T& convert_type(U&)
 T& convert_type(U& _in)
    ^
prog.cpp:46:4: note:   template argument deduction/substitution failed:
prog.cpp:45:132: error: no type named 'type' in 'struct std::enable_if<false, int>'
 template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_lvalue_reference_t<std::add_const_t<U>>>::value, int> = 0>
                                                                                                                                    ^
prog.cpp:45:132: note: invalid template non-type parameter
prog.cpp:55:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_pointer<U>::type>::value, int>::type <anonymous> > T convert_type(U&)
 T convert_type(U& _in)
   ^
prog.cpp:55:3: note:   template argument deduction/substitution failed:
prog.cpp:54:105: error: no type named 'type' in 'struct std::enable_if<false, int>'
 template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_pointer_t<U>>::value, int> = 0>
                                                                                                         ^
prog.cpp:54:105: note: invalid template non-type parameter
prog.cpp:61:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_const<U>::type>::value, int>::type <anonymous> > T convert_type(U&)
 T convert_type(U& _in)
   ^
prog.cpp:61:3: note:   template argument deduction/substitution failed:
prog.cpp:60:103: error: no type named 'type' in 'struct std::enable_if<false, int>'
 template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
                                                                                                       ^
prog.cpp:60:103: note: invalid template non-type parameter
prog.cpp:67:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_pointer<typename std::add_const<U>::type>::type>::value, int>::type <anonymous> > T convert_type(U&)
 T convert_type(U& _in)
   ^
prog.cpp:67:3: note:   template argument deduction/substitution failed:
prog.cpp:66:123: error: no type named 'type' in 'struct std::enable_if<false, int>'
 template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_pointer_t<std::add_const_t<U>>>::value, int> = 0>
                                                                                                                           ^
prog.cpp:66:123: note: invalid template non-type parameter
prog.cpp:259:219: error: return-statement with a value, in function returning 'void' [-fpermissive]
     return (obj->*Method)(convert_type<typename function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::template arg<paramIndex>::type, typename ParamType::Type>(std::get<paramIndex>(params))...);
                                                                                                                                                                                                                           ^
prog.cpp: In instantiation of 'ReturnType CallMethodRet(bool&, Type*, std::tuple<typename ParamType::Type ...>&, std::index_sequence<paramIndex ...>) [with Type = O; ReturnType = int; MethodType = int (O::*)(int, std::basic_string<char>, bool&, const char*); typename std::enable_if<function_traits<std::function<typename std::remove_pointer<MethodType>::type> >::isClassContainer, MethodType>::type Method = &O::func_i; ParamType = Param<int>, Param<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ParamOut<bool>, Param<char*>; unsigned int ...paramIndex = 0u, 1u, 2u, 3u; std::index_sequence<paramIndex ...> = std::integer_sequence<unsigned int, 0u, 1u, 2u, 3u>]':
prog.cpp:265:77:   required from 'ReturnType CallMethodRet(bool&, Type*, std::tuple<typename ParamType::Type ...>&) [with Type = O; ReturnType = int; MethodType = int (O::*)(int, std::basic_string<char>, bool&, const char*); MethodType Method = &O::func_i; ParamType = {Param<int>, Param<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ParamOut<bool>, Param<char*>}]'
prog.cpp:285:83:   required from 'bool ExecuteMethod(Type*, unsigned int, std::vector<void*>&, ReturnType&) [with Type = O; ReturnType = int; MethodType = int (O::*)(int, std::basic_string<char>, bool&, const char*); typename std::enable_if<(! function_traits<std::function<typename std::remove_pointer<MethodType>::type> >::returnsVoid), MethodType>::type Method = &O::func_i; ParamType = {Param<int>, Param<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, ParamOut<bool>, Param<char*>}]'
prog.cpp:375:176:   required from here
prog.cpp:259:186: error: no matching function for call to 'convert_type(char*&)'
     return (obj->*Method)(convert_type<typename function_traits<std::function<typename std::remove_pointer<MethodType>::type>>::template arg<paramIndex>::type, typename ParamType::Type>(std::get<paramIndex>(params))...);
                                                                                                                                                                                          ^
prog.cpp:17:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same< <template-parameter-1-1>, <template-parameter-1-2> >::value, int>::type <anonymous> > T convert_type(U)
 T convert_type(U _in)
   ^
prog.cpp:17:3: note:   template argument deduction/substitution failed:
prog.cpp:16:85: error: no type named 'type' in 'struct std::enable_if<false, int>'
 template<typename T, typename U, std::enable_if_t<std::is_same<T, U>::value, int> = 0>
                                                                                     ^
prog.cpp:16:85: note: invalid template non-type parameter
prog.cpp:24:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_const<U>::type>::value, int>::type <anonymous> > T convert_type(U)
 T convert_type(U _in)
   ^
prog.cpp:24:3: note:   template argument deduction/substitution failed:
prog.cpp:23:103: error: no type named 'type' in 'struct std::enable_if<false, int>'
 template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
                                                                                                       ^
prog.cpp:23:103: note: invalid template non-type parameter
prog.cpp:34:4: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_const<U>::type>::value, int>::type <anonymous> > T& convert_type(U&)
 T& convert_type(U& _in)
    ^
prog.cpp:34:4: note:   template argument deduction/substitution failed:
prog.cpp:33:103: error: no type named 'type' in 'struct std::enable_if<false, int>'
 template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
                                                                                                       ^
prog.cpp:33:103: note: invalid template non-type parameter
prog.cpp:40:4: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_lvalue_reference<U>::type>::value, int>::type <anonymous> > T& convert_type(U&)
 T& convert_type(U& _in)
    ^
prog.cpp:40:4: note:   template argument deduction/substitution failed:
prog.cpp:39:114: error: no type named 'type' in 'struct std::enable_if<false, int>'
 template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_lvalue_reference_t<U>>::value, int> = 0>
                                                                                                                  ^
prog.cpp:39:114: note: invalid template non-type parameter
prog.cpp:46:4: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_lvalue_reference<typename std::add_const<U>::type>::type>::value, int>::type <anonymous> > T& convert_type(U&)
 T& convert_type(U& _in)
    ^
prog.cpp:46:4: note:   template argument deduction/substitution failed:
prog.cpp:45:132: error: no type named 'type' in 'struct std::enable_if<false, int>'
 template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_lvalue_reference_t<std::add_const_t<U>>>::value, int> = 0>
                                                                                                                                    ^
prog.cpp:45:132: note: invalid template non-type parameter
prog.cpp:55:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_pointer<U>::type>::value, int>::type <anonymous> > T convert_type(U&)
 T convert_type(U& _in)
   ^
prog.cpp:55:3: note:   template argument deduction/substitution failed:
prog.cpp:54:105: error: no type named 'type' in 'struct std::enable_if<false, int>'
 template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_pointer_t<U>>::value, int> = 0>
                                                                                                         ^
prog.cpp:54:105: note: invalid template non-type parameter
prog.cpp:61:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_const<U>::type>::value, int>::type <anonymous> > T convert_type(U&)
 T convert_type(U& _in)
   ^
prog.cpp:61:3: note:   template argument deduction/substitution failed:
prog.cpp:60:103: error: no type named 'type' in 'struct std::enable_if<false, int>'
 template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_const_t<U>>::value, int> = 0>
                                                                                                       ^
prog.cpp:60:103: note: invalid template non-type parameter
prog.cpp:67:3: note: candidate: template<class T, class U, typename std::enable_if<std::is_same<T, typename std::add_pointer<typename std::add_const<U>::type>::type>::value, int>::type <anonymous> > T convert_type(U&)
 T convert_type(U& _in)
   ^
prog.cpp:67:3: note:   template argument deduction/substitution failed:
prog.cpp:66:123: error: no type named 'type' in 'struct std::enable_if<false, int>'
 template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_pointer_t<std::add_const_t<U>>>::value, int> = 0>
                                                                                                                           ^
prog.cpp:66:123: note: invalid template non-type parameter
stdout
Standard output is empty