std :: function和function模板

时间:2019-06-09 12:41:39

标签: c++ templates std-function

我想将通过函数模板定义的函数分配给std :: function,但是出现无法解析的重载函数类型错误

// template
template <std::function<double(double)> &f, int i>
double iter(double x)
{
   for (int j=0; j<i; j++)
   {
      x=f(x);
   }
   return x;
}

// function
double poly(double x)
{
   return pow(x,2)-2;
}

int main()
{
   // I expect on the right the object iter to be of type
   // double(double), but the compiler says is unresolved function type
   std::function<double(double)> f= iter<poly, 2>;
   std::cout << f(1.0) <<std::endl;
   return 0;
}

2 个答案:

答案 0 :(得分:2)

template <std::function<double(double)> &f, int i>
double iter(double x)

此模板函数的第一个参数是a(对a的引用)std::function。忽略这种方法的其他一些问题,最大的问题是:

iter<poly, 2>;

poly不是std::function。这是一种朴素的花园式功能。您可以使用普通函数指针来构造兼容的std::function,但这不是在构造对象的实例。我们在这里使用模板参数,这不是一回事。

您可以简单地将可调用对象作为参数传递给iter(),而不使用模板参数。像这样:

#include <functional>
#include <cmath>
#include <iostream>

template<int i>
double iter(const std::function<double(double)> &f, double x)
{
   for (int j=0; j<i; j++)
   {
      x=f(x);
   }
   return x;
}

// function
double poly(double x)
{
   return pow(x,2)-2;
}

int main()
{
   std::function<double(double)> f=
       []
       (double v)
       {
           return iter<2>(poly, v);
       };

   std::cout << f(1.0) <<std::endl;
   return 0;
}

目前尚不清楚这是否实际上是您想要的计算,但这是一般的想法。根据需要进行调整。在这里,您正在使用poly(它被用作函数指针)来构造std::function

答案 1 :(得分:1)

在C ++ 20之前,模板参数只能使用以下类型:

  • std :: nullptr_t(自C ++ 11起);
  • 整数类型;
  • 指针类型(指向对象或函数);
  • 指向成员类型的指针(指向成员对象或成员函数);
  • 枚举类型。

由于std::function<double(double)> &都不是,所以不能在模板参数中使用它。

但是,您可以使用指向具有外部链接的函数的指针,如下所示:

#include <cmath>
#include <functional>
#include <iostream>

// template
template <double(*f)(double), int i>
double iter(double x)
{
   for (int j=0; j<i; j++)
   {
      x=f(x);
   }
   return x;
}

// function
double poly(double x)
{
   return std::pow(x,2)-2;
}

int main()
{
   // this compiles!
   std::function<double(double)> f= iter<poly, 2>;
   std::cout << f(1.0) <<std::endl;
   return 0;
}