如何从任意函数中创建仿函数?

How do I make a functor out of an arbitrary function?

我有一堆函数想用作仿函数(也就是说,使用类型而不是将指针传递给函数或任何其他类型的数据)。

是否有 elegant/idiomatic/standard 使用标准库或标准库 + 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)...);
    }
};

备注:

如果函数没有被重载,你可以在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 旨在通过引入 "lift" 运算符.

来解决此问题 A. Sutton 的

P0119 通过允许重载集在作为参数传递时基本上为您生成 "wrapper lambda" 以不同的方式解决了这个问题。

在接受任何这些建议之前,您可以使用 漂亮 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)...); \
    }

首先,固定类型的具体示例。

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);

live example.

您不能将函数的重载集作为对象进行操作;唯一的方法是通过文字。因此宏。

这具有完美转发的所有常见缺陷。一般无法避免这些缺陷。