fork download
  1. #include <tuple>
  2. #include <iostream>
  3. #include <typeinfo>
  4. #include <vector>
  5. #include <iterator>
  6. #include <algorithm>
  7.  
  8.  
  9. template <class T, class... Args>
  10. class Runnable
  11. {
  12. public:
  13. void print() const
  14. {
  15. std::vector<std::string> names {(typeid(Args).name())...};
  16. std::cout << typeid(T).name() << "(";
  17. std::copy(names.begin(), names.end(), std::ostream_iterator<std::string>(std::cout, ", "));
  18. std::cout << ")\n";
  19. };
  20. };
  21.  
  22. /** PackDiff:
  23.  * Template Metafunction to deduce the difference of two parameter packs.
  24.  * To distinguish two packs we have to brace them in two tuples
  25.  */
  26. template <class Tup1, class Tup2> struct PackDiff;
  27.  
  28. /** Basic algorithm: (T, X1...) - (T, X2...) = (X1...) - (X2...) */
  29. template <class T, class... Pack1, class... Pack2>
  30. struct PackDiff<std::tuple<T, Pack1...>, std::tuple<T, Pack2...>>
  31. : PackDiff<std::tuple<Pack1...>, std::tuple<Pack2...>> {};
  32.  
  33. /** End of recursion: (X1...) - () = (X1...) */
  34. template <class... Pack1>
  35. struct PackDiff<std::tuple<Pack1...>, std::tuple<>>
  36. {
  37. typedef std::tuple<Pack1...> type;
  38. };
  39.  
  40. /** Mismatch: (T, X1...) - (U, X2...) is undefined */
  41. template <class T1, class... Pack1, class T2, class... Pack2>
  42. struct PackDiff<std::tuple<T1, Pack1...>, std::tuple<T2, Pack2...>>
  43. { typedef struct PACK_MISMATCH {} type; };
  44.  
  45. /** Rest: () - (X2...) is undefined */
  46. template <class... Pack2>
  47. struct PackDiff<std::tuple<>, std::tuple<Pack2...>>
  48. { typedef struct LEFT_PACK_TOO_SHORT{} type; };
  49.  
  50.  
  51.  
  52. //make Runnable Type of T and a diff tuple:
  53. template <class T, class Tup1>
  54. struct MakeRunnableType;
  55.  
  56. template <class T, class... Pack>
  57. struct MakeRunnableType<T, std::tuple<Pack...>>
  58. {
  59. typedef Runnable<T, Pack...> type;
  60. };
  61.  
  62.  
  63. template<typename... AllArgs, typename T, typename... SomeArgs>
  64. auto makeRunnable(T (*FunctionType)(AllArgs...), SomeArgs... ct_args)
  65. -> typename MakeRunnableType<T, typename PackDiff<std::tuple<AllArgs...>, std::tuple<SomeArgs...>>::type>::type*
  66. {
  67. typedef typename PackDiff<std::tuple<AllArgs...>, std::tuple<SomeArgs...>>::type PackDiff_t;
  68. typedef typename MakeRunnableType<T, PackDiff_t>::type ReturnType;
  69. return new ReturnType();
  70. }
  71.  
  72. int print_function(char arg1, int arg2, const char* arg3) { return 0; };
  73.  
  74. int main()
  75. {
  76. auto f = makeRunnable(&print_function, 'C', -3);
  77. f-> print();
  78. delete f;
  79. auto f2 = makeRunnable(&print_function, 'C');
  80. f2-> print();
  81. delete f2;
  82. }
Success #stdin #stdout 0s 2988KB
stdin
Standard input is empty
stdout
i(PKc, )
i(i, PKc, )