#include <tuple>
#include <iostream>
#include <typeinfo>
#include <vector>
#include <iterator>
#include <algorithm>


template <class T, class... Args>
class Runnable
{
public:    
  void print() const
  {
    std::vector<std::string> names {(typeid(Args).name())...};
    std::cout << typeid(T).name() << "(";
    std::copy(names.begin(), names.end(), std::ostream_iterator<std::string>(std::cout, ", "));
    std::cout << ")\n";
  };  
};

/** PackDiff: 
 *  Template Metafunction to deduce the difference of two parameter packs.
 *  To distinguish two packs we have to brace them in two tuples
 */
template <class Tup1, class Tup2> struct PackDiff;

/** Basic algorithm: (T, X1...) - (T, X2...) = (X1...) - (X2...) */
template <class T, class... Pack1, class... Pack2>
struct PackDiff<std::tuple<T, Pack1...>, std::tuple<T, Pack2...>>
  : PackDiff<std::tuple<Pack1...>, std::tuple<Pack2...>> {};

/** End of recursion: (X1...) - () = (X1...) */
template <class... Pack1>
struct PackDiff<std::tuple<Pack1...>, std::tuple<>>
{
  typedef std::tuple<Pack1...> type;
};

/** Mismatch: (T, X1...) - (U, X2...) is undefined */
template <class T1, class... Pack1, class T2, class... Pack2>
struct PackDiff<std::tuple<T1, Pack1...>, std::tuple<T2, Pack2...>>
{ typedef struct PACK_MISMATCH {} type; };

/** Rest: () - (X2...) is undefined */  
template <class... Pack2>
struct PackDiff<std::tuple<>, std::tuple<Pack2...>>
{ typedef struct LEFT_PACK_TOO_SHORT{} type; };



//make Runnable Type of T and a diff tuple:
template <class T, class Tup1>
struct MakeRunnableType;

template <class T, class... Pack>
struct MakeRunnableType<T, std::tuple<Pack...>>
{
  typedef Runnable<T, Pack...> type;
};


template<typename... AllArgs, typename T, typename... SomeArgs> 
auto makeRunnable(T (*FunctionType)(AllArgs...), SomeArgs... ct_args)
  -> typename MakeRunnableType<T, typename PackDiff<std::tuple<AllArgs...>, std::tuple<SomeArgs...>>::type>::type*
{
  typedef typename PackDiff<std::tuple<AllArgs...>, std::tuple<SomeArgs...>>::type PackDiff_t;
  typedef typename MakeRunnableType<T, PackDiff_t>::type ReturnType;
  return new ReturnType();
}

int print_function(char arg1, int arg2, const char* arg3) { return 0; };

int main()
{
  auto f = makeRunnable(&print_function, 'C', -3);
  f-> print();
  delete f;
  auto f2 = makeRunnable(&print_function, 'C');
  f2-> print();
  delete f2;
}