std ::带模板的函数,类型问题,没有匹配的调用函数

我有一个这样定义的函数:

template <size_t SIZE>
double MyFun(std::function<double(std::array<double,SIZE>&)> f,std::array<double,SIZE> &x,SIZE> &y){
   instructions;
}

和另一个函数,应该是前一个的参数,其定义如下:

double MyFun2(std::array<double,3> &var){
  instructions;
}

如果我尝试这样称呼“ MyFun”:

    double something;
    std::array<double,3> var = {...};
    std::array<double,3> var2 = {...};
    something = MyFun(MyFun2,var,var2);

我收到此错误:

error: no matching function for call to ‘MyFun(double (&)(std::array<double,3>&),3>&,3>&)’
note:   template argument deduction/substitution failed:
note:   mismatched types ‘std::function<double(std::array<double,SIZE>&)>’ and ‘double (*)(std::array<double,3>&)’

此外,如果我尝试将“ MyFun2”存储在带有“自动”的变量中

  auto function = MyFun2;

“功能”的类型为:

  double (*function)(std::array<double,3UL> &var)

,我也不能将“ function”用作MyFun的参数。 我发现的唯一解决方案是通过指定正确的类型来对“ MyFun2”进行某种类型的投射:

  double something;
  std::array<double,3> var = {...};
  std::array<double,3> var2 = {...};

  std::function<double(std::array<double,3>&)> function = MyFun2;
  something = MyFun(function,var2);

通过这种方式,将“功能”作为“ MyFun”的第一个参数传递。 但是,为什么我会有这样的歧义,而不能仅通过输入MyFun2作为第一个参数来调用MyFun?为什么汽车不能弄清楚“正确”的类型?

谢谢:)

hell_liul 回答:std ::带模板的函数,类型问题,没有匹配的调用函数

模板参数推导的工作原理与您传入的参数完全匹配。它不考虑转换。

因为传递MyFun与传递函数指针相同,并且您的模板正在寻找std::function,所以推导失败。

惯用方法是接受模板中的任何可调用对象,而不必担心签名。由于您将在模板中调用该可调用对象,因此,如果签名不匹配,您仍然会遇到编译时错误。

template <typename Func,size_t SIZE>
double MyFun(F f,std::array<double,SIZE> &x,SIZE> &y){
   // go ahead and use f(x,y); for example
}

此方法还有一个额外的好处,即您不仅限于一种可调用类型。我们可以传入一个函数指针,一个std :: function,一个Functor。任何支持语法f(...);

的东西 ,

您遇到no matching function for call to...错误std::function,没有推论指南来推论函数指针的签名。

执行此操作时:

auto function = MyFun2;

函数MyFun2衰减为函数指针。将函数的值存储在变量中没有任何意义,因为函数的值是多少?这是一堆机器指令。为什么要复制它?该语言假设您不会,因此函数会退化为函数指针。以上等同于此:

double (*function)(std::array<double,3> &var) = MyFun2;

您找到了解决此错误的方法,那就是直接从函数指针构造一个std::function。另一个解决方案是完全避免std::function

template <size_t SIZE>
double MyFun(double (*f)(std::array<double,SIZE>&),SIZE> &y){
   instructions;
}

所以现在您的原始示例起作用了

something = MyFun(MyFun2,var,var2);
,

要创建std::function的对象,您需要使用std::bind(&MyFun2,std::placeholders::_1)。供参考address cppreference

您的代码也有一些问题。 std::funcion很大,在x64中将占用64个字节,因此复制它不是最佳解决方案。您既可以将其作为const引用,也可以将其作为r值引用传递给RAII。

#include <array>
#include <iostream>
#include <functional>

#include <numeric>

// typedef Alias for convinence
template <size_t sz>
using Wrapped_t = std::function<double(const std::array<double,sz>&)>;

template <size_t sz>
double MyFunc(const Wrapped_t<sz> &f,const std::array<double,sz> &arr1,sz> &arr2)
{
    // some dummy implementation for demonstratio purposes 
    return f(arr1) + f(arr2);
}

double MyFunc2(const std::array<double,3> &arr)
{
    // some dummy implementation for demonstratio purposes 
    return std::accumulate(arr.cbegin(),arr.cend(),0);
}

int main()
{
    std::cout << sizeof(Wrapped_t<3>) << std::endl;     // 64 bytes for x64 build. You are better off not copying your function object


    std::cout << MyFunc2({ 3.14,2.18,2.895 }) << std::endl; // invoking your function as regular

    // to create an std::function object you should use std::bind
    Wrapped_t<3> wrapped = std::bind(&MyFunc2,std::placeholders::_1);
    std::cout << wrapped({ 3.14,2.895 }) << std::endl; // invoking your function wrapped to std::function

    std::array<double,3> arr1{ 3,14,28 },arr2{ 2,18,9 };

    // this is what you asked for
    std::cout << MyFunc(wrapped,arr1,arr2) << std::endl;


    return 0;
}

本文链接:https://www.f2er.com/2999398.html

大家都在问