TypeToEnum<std::forward<Args>>::value
to TypeToEnum<Args>::value...
, but I'd instead do
template<typename Return,typename... Args>
Return invoke(Args...&& args){
static const int type_check[] = {
TypeToEnum<Return>::value,TypeToEnum<typename std::decay<Args>::type>::value...
};
if (type_check[0] != return_type)
throw std::exception("Invalid return type for given call");
for (int i = 1; i <= sizeof...(Args); i++)
{
if (type_check[i] != argument_types[i])
throw std::exception("Invalid argument type for the given call");
}
typedef Return(*func_t)(typename std::decay<Args>::type...);
return static_cast<func_t>(function)( std::forward<Args>(args) );
}
as a first pass. I would then replace decay
with a custom type mapping that handles std::reference_wrapper
properly, so callers can say "I expect this argument to be a ref" by saying invoke( std::ref(x) )
.
Next, I would consider using the typeid
instead of all of your machinery. Your hash isn't perfectly reliable, among other problems.