在 C++11 中,是否可以将模板函数包装在 std::function 中?

In C++11, is it possible to wrap a template function in a std::function?

如果我在 C++11 中有一个模板函数,是否可以将它包装在 std::function 中?

我的问题是这样的:

我有一个通用函数(比如求和函数),其中 return 类型取决于参数的类型:

template <typename T>
auto sum(T const& a, T const& b) -> decltype(a+b)
{
    return a + b;
}

并且我想将它包装在 std:function 中以用于特定的参数类型(比如 int)。我正在尝试以下操作:

int main()
{
  std::function<int(int,int)> intsum = std::bind(static_cast<int(*)(int,int)>(&sum), std::placeholders::_1, std::placeholders::_2);
  auto mysum = intsum(2, 4);

  std::cout << mysum << std::endl;

  return 0;
}

但是编译上面的代码会产生错误:

error: invalid static_cast from type ‘<unresolved overloaded function type>’ to type ‘int (*)(int, int)

有什么方法可以实现我想要做的事情吗?

您可以专门化模板并使用它:

std::function<int(int,int)> intsum = sum<int>;
auto mysum = intsum(2, 4);

std::cout << mysum << std::endl;

您不能将通用函数包装在 std::function 特定实例中,这正是您所要求的。

但是,您可以包装通用函数的完全指定的 实例 ,这正是您的代码实际要执行的操作:

template <typename T>
auto sum(T const& a, T const& b) -> decltype(a+b)
{
  return a + b;
}

#include <functional>
#include <iostream>

int main()
{
  std::function<int(int,int)> intsum =
    std::bind(sum<int>,
              std::placeholders::_1, std::placeholders::_2);
  auto mysum = intsum(2, 4);

  std::cout << mysum << std::endl;
}

或者更简单地说

  std::function<int(int,int)> intsum = sum<int>;

当然,如果您真的不需要 包装,只需:

  auto mysum = sum(2, 4);

你的问题是类型错误。

sum<?> 没有 int(int,int) 重载。所以当你 static_cast<int(*)(int,int)(sum) 时,它会抱怨它无法进行转换。

存在 int(int const&,int const&) 过载。如果你 static_cast<int(*)(int const&, int const&)>(sum) 它会起作用。

如果没有这样的重载指向,函数模板到函数指针的转换将不起作用。

存在三种合理的方法。

首先,转换为正确的类型。 static_cast<int(*)(int const&,int const&)>(sum).

其次,明确的专业化。 sum<int> 而不是 static_cast 表达式。

三、创建重载集对象:

struct sum_t{
  template<class...Args>
  auto operator()(Args&&...args)const
  -> decltype(sum(std::declval<Args>()...))
  {
    return sum(std::forward<Args>(args)...);
  }
};
static sum_t sum_os;

并将 static_cast<int(*)(int,int)>(sum) 替换为 sum_os

sum_os 可以传递给 bindstd::function 或其他任何东西,重载决议被推迟到调用代码。

作为奖励,编译器比函数指针调用更容易优化。

作为负数,完美转发是不完美的。

重载集的 C++14 版本是:

[](auto&&...args)->
decltype(sum(decltype(args)(args)...))
{ return sum(decltype(args)(args)...); }

可以变成宏:

#define OVERLOAD_SET(FUNC) \
  [](auto&&...args)-> \
  decltype(FUNC(decltype(args)(args)...)) \
  { return FUNC(decltype(args)(args)...); }

这让您只需在使用时执行 OVERLOAD_SET(sum),然后传入整个重载集。