我有一堆函数,我想用作函子(也就是说,使用类型而不是传递指向函数的指针,或任何其他类型的数据)。
使用标准库或标准库+ Boost是否有优雅/惯用/标准的方法?也许以某种方式使用bind()
?
或者我应该采用简单化的方法(好吧,简单化),例如:
template<typename Function, Function& F, typename... Parameters>
struct functor {
using function_type = Function;
using parameters_as_tuple_type = std::tuple<Parameters...>;
auto operator() (Parameters&&... params) ->
decltype(F(std::forward<Parameters>(params)...))
{
return F(std::forward<Parameters>(params)...);
}
};
注意:
答案 0 :(得分:3)
如果函数没有重载,可以在C ++ 17中执行此操作:
template <auto F>
auto to_function_object()
{
return [](auto&&... xs) -> decltype(auto)
{
return F(std::forward<decltype(xs)>(xs)...);
};
}
void a(int) { }
int main()
{
auto af = to_function_object<a>();
af(1);
}
如果函数超载,则无法将其重载集作为参数传递给另一个函数或模板。您被迫在现场手动编写包装器lambda。例如:
void foo(int) { }
void foo(char) { }
// ...
bar([](auto x){ return foo(x); });
N3617旨在通过引入&#34; lift&#34;来解决这个问题。操作
A. Sutton的P0119通过允许重载集基本上生成&#34;包装器lambda&#34;以不同的方式解决问题。为你而作为参数传递。
在接受任何提案之前,您可以使用漂亮的 C ++ 14宏代替:
#define LIFT(f) \
[](auto&&... xs) noexcept(noexcept(f(std::forward<decltype(xs)>(xs)...))) \
-> decltype(f(std::forward<decltype(xs)>(xs)...)) \
{ \
return f(std::forward<decltype(xs)>(xs)...); \
}
答案 1 :(得分:1)
首先,一个固定类型的具体例子。
int foo( int );
void foo( double );
struct foo_t {
template<class...Args>
auto operator()(Args&&...args)const
->decltype( foo( std::declval<Args>()... ) )
{ return ( foo( std::forward<Args>(args)... ) ); }
};
现在foo_t
是一个通过完美转发调用foo
重载的对象。
使它通用:
#define RETURNS(...) noexcept(noexcept(__VA_ARGS__)) -> decltype(__VA_ARGS__) { return __VA_ARGS__; }
#define OVERLOAD_SET_TYPE(...) \
struct { \
template<class...Args> \
auto operator()(Args&&...args)const \
RETURNS( __VA_ARGS__( std::forward<Args>(args)... ) ) \
}
所以我们可以做到
using foo_t = OVERLOAD_SET_TYPE(foo);
您无法将函数的重载集作为对象进行操作;唯一的方法是文本。因此宏。
这具有完美转发的所有常见缺陷。没有办法一般避免这些不完美之处。