Я пытаюсь написать переменную оболочку шаблона для любой функции, которая будет передана ей, и (возможно) ее возвращаемое значение будет возвращено.
Пока я придумал код, приведенный ниже, но я действительно ненавижу, что мне нужно 6 различных перегрузок функций, 3 для типов возвращаемых значений void и 3 для типов возвращаемых значений void.
// Void return type
// Template for non-member functions
template <typename Callable, typename... Args>
std::enable_if_t<std::is_void<std::result_of_t<Callable(Args...)> >::value
&& std::is_member_function_pointer<Callable>::value == false>
call(Callable worker, Args... params)
{
worker(std::forward<Args>(params)...);
}
// Template for member functions (general)
template <typename Callable, typename... Args>
std::enable_if_t<std::is_void<std::result_of_t<Callable(Args...)> >::value
&& std::is_member_function_pointer<Callable>::value>
call(Callable worker, Args... params)
{
call(std::forward<Callable>(worker), std::forward<Args>(params)...);
}
// Template for member functions (object instance extractor)
template <typename Callable, typename Object, typename... Args>
std::enable_if_t<std::is_void<std::result_of_t<Callable(Args...)> >::value
&& std::is_member_function_pointer<Callable>::value>
call(Callable worker, Object object, Args... params)
{
auto fn = std::mem_fn(worker);
fn(std::forward<Object>(object), std::forward<Args>(params)...);
}
// Non-void return types
// Template for non-member functions
template <typename Callable, typename... Args>
std::enable_if_t<std::is_void<std::result_of_t<Callable(Args...)> >::value == false
&& std::is_member_function_pointer<Callable>::value == false
, std::result_of_t<Callable(Args...)> >
call(Callable worker, Args... params)
{
return worker(std::forward<Args>(params)...);
}
// Template for member functions (general)
template <typename Callable, typename... Args>
std::enable_if_t<std::is_void<std::result_of_t<Callable(Args...)> >::value == false
&& std::is_member_function_pointer<Callable>::value
, std::result_of_t<Callable(Args...)> >
call(Callable worker, Args... params)
{
return call(std::forward<Callable>(worker), std::forward<Args>(params)...);
}
// Template for member functions (object instance extractor)
template <typename Callable, typename Object, typename... Args>
std::enable_if_t<std::is_void<std::result_of_t<Callable(Args...)> >::value == false
&& std::is_member_function_pointer<Callable>::value
, std::result_of_t<Callable(Args...)> >
call(Callable worker, Object object, Args... params)
{
auto fn = std::mem_fn(worker);
return fn(std::forward<Object>(object), std::forward<Args>(params)...);
}
Есть ли способ избавиться от некоторых из этих перегрузок? Этот подход работает хорошо, но с точки зрения кода мне бы хотелось что-то немного короче.