【发布时间】:2019-03-29 15:14:19
【问题描述】:
我正在尝试为要传递给它的任何函数编写一个可变参数模板包装器,并且(可能)它是要返回的返回值。
现在我想出了下面的代码,但我真的很讨厌我需要 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)...);
}
有什么办法可以摆脱这些重载?事实证明,这种方法效果很好,但在代码方面我真的想要一些更短的东西。
【问题讨论】:
-
你仅限于 C++14 吗? C++17 提供了
std::invoke,它就是这样做的。 -
此外,在返回
void的函数中执行return void_returning_function();是合法的,因此对于 void 函数您真的不需要特殊情况。 -
@NathanOliver,不幸的是,现在我仅限于 C++14,所以
std::invoke是不行的。那是我的第一次。至于return void_returning_function();,我不记得了,谢谢!
标签: c++ templates c++14 variadic-templates