调用函数时找不到std :: function构造函数

时间:2012-04-15 13:26:10

标签: c++ c++11

我有一个声明如下的函数;它的确切工作与此无关。

template<typename T>
std::pair<int, int>
partition3(T *pT, const int N, const T &Kq, const int w,
           std::function<int(const T&, const T&, int)> P);

在通话网站上,我尝试执行以下操作:

bool partition3_test()
{
  struct cmp
  {
    int operator()(int x, int y, int) const
    { return x-y; }
  };

  int V1[11] = { 3, 7, 1, 7, 7, 8, 10, 2, 16, 4, 3 },
      V2[11] = { 3, 6, 1, 6, 6, 8, 10, 2, 16, 4, 3 };

  std::function<int(const int&, const int&, int)> F = cmp();

  std::pair<int, int>
    p1  = partition3(V1, 11, 7, 0, cmp()),
    p2  = partition3(V2, 11, 7, 0, cmp());

  return false;
}

对于partition3的两次调用,编译器(MSVC 2010)抱怨它无法推断出最后一个参数的模板参数。如果我将cmp()替换为F,则代码会编译并正常运行。

我有两个问题:

  1. 为什么我会收到错误? [编译器错误或一些神秘的C ++规则?]
  2. 如果没有先明确构建F
  3. ,我怎样才能达到同样的效果?

    (目前,我已通过在partition3上引入另一个模板参数并将P声明为该模板类型来解决此问题。)

1 个答案:

答案 0 :(得分:4)

cmp()实际上根本不是std::function。复制初始化工作的事实可能会混淆问题,但是使用转换构造函数必须使用某种包装器对象,我很惊讶它对一个临时的仿函数对象起作用(啊,检查标准吧显然是制作仿真器的副本)。

除此之外,函数参数不匹配(按值传递和传递const引用是源兼容的,但不兼容运行时调用),这又需要一个适配器。 / p>

最好的解决方案是使模板函数更通用,这样它也适用于原始函数指针和任意函子对象,而不仅仅是std::function

template<typename T, typename Functor>
std::pair<int, int> partition3(T *pT, const int N, const T &Kq, const int w,
                               const Functor& P);

如果由于某种原因你真的想使用std::function(例如你需要虚拟调度),你可以。与Nawaz写的相反,这个错误是一个可推导的上下文,但不止一种类型适合(这是std::function的适配器/包装器性质变得重要的地方,因为类型不必与参数完全匹配,它只需要兼容。std::function<int(const long&, const long&, int)>也匹配。)

使用不可推导的上下文,这样编译器甚至不会尝试使用仿函数来推导T

template<typename T, typename Functor>
std::pair<int, int> partition3(T *pT, const int N, const T &Kq, const int w,
                               std::function<std::identity<const T>::type&, std::identity<const T>::type&, int> P);