简体   繁体   中英

std::function and function templates

I want to assign to a std::function a function defined through a function template, but I get unresolved overloaded function type errors

// 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;
}
template <std::function<double(double)> &f, int i>
double iter(double x)

The first parameter of this template function is a (reference to a) std::function . Ignoring a few other problems with this approach, the biggest issue is that:

iter<poly, 2>;

poly is not a std::function . It is a plain, garden-variety function. You can use a plain function pointer to construct a compatible std::function , but this is not constructing an instance of an object. We're working with template parameters here, which is not the same thing.

You can simply pass the callable object as a parameter to iter() , instead of using a template parameter. Like this:

#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;
}

It is not clear if this was actually your intended calculation, but this is the general idea. Adjust as needed. Here, you're using poly , which is evaluated as a function pointer, to construct a std::function .

Before C++20, the only allowed types for template parameters are:

  • std::nullptr_t (since C++11);
  • an integral type;
  • a pointer type (to object or to function);
  • a pointer to member type (to member object or to member function);
  • an enumeration type.

Since std::function<double(double)> & is none of these, you cannot use it in your template parameter.

You can, however, use a pointer to a function which has external linkage, like this:

#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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM