std::function有模板,类型问题,没有匹配的调用函数
std::function with template, type problem, no matching function for call
我有一个这样定义的函数:
template <size_t SIZE>
double MyFun(std::function<double(std::array<double,SIZE>&)> f, std::array<double,SIZE> &x, std::array<double,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>&), std::array<double, 3>&, std::array<double, 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"
的变量中
auto function = MyFun2;
给"function"的类型是:
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, var, var2);
这样,传递 "function" 作为 "MyFun" 的第一个参数就可以了。
但是为什么我有这样的歧义,我不能通过键入 MyFun2 作为第一个参数来调用 MyFun?为什么 auto 无法识别 "right" 类型?
谢谢:)
您收到 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>&), std::array<double, SIZE> &x, std::array<double, SIZE> &y){
instructions;
}
现在您的原始示例有效了
something = MyFun(MyFun2, var, var2);
为了创建std::function
的对象,您需要使用std::bind(&MyFun2, std::placeholders::_1)
。供参考 address cppreference .
您的代码也存在一些问题。 std::funcion
比较大,在 x64 中将占用 64 个字节,因此复制它不是最好的解决方案。您可以将其作为 const 引用传递,也可以作为 RAII 目的的 r 值引用传递。
#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, const std::array<double, 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.18, 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;
}
模板参数推导通过精确匹配您传入的参数来工作。它不考虑转换。
由于传递 MyFun
与传递函数指针相同,并且您的模板正在寻找 std::function
推导失败。
惯用的方法是接受模板中的任何可调用对象,而不用担心签名。由于您将在模板中调用该可调用对象,因此如果签名不匹配,您仍然会遇到编译时错误。
template <typename Func, size_t SIZE>
double MyFun(F f, std::array<double,SIZE> &x, std::array<double,SIZE> &y){
// go ahead and use f(x, y); for example
}
这种方法还有一个额外的好处,即您不限于一种类型的可调用对象。我们可以传入一个函数指针,一个 std::function,一个 Functor。任何支持语法 f(...);
的东西
我有一个这样定义的函数:
template <size_t SIZE>
double MyFun(std::function<double(std::array<double,SIZE>&)> f, std::array<double,SIZE> &x, std::array<double,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>&), std::array<double, 3>&, std::array<double, 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"
的变量中 auto function = MyFun2;
给"function"的类型是:
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, var, var2);
这样,传递 "function" 作为 "MyFun" 的第一个参数就可以了。 但是为什么我有这样的歧义,我不能通过键入 MyFun2 作为第一个参数来调用 MyFun?为什么 auto 无法识别 "right" 类型?
谢谢:)
您收到 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>&), std::array<double, SIZE> &x, std::array<double, SIZE> &y){
instructions;
}
现在您的原始示例有效了
something = MyFun(MyFun2, var, var2);
为了创建std::function
的对象,您需要使用std::bind(&MyFun2, std::placeholders::_1)
。供参考 address cppreference .
您的代码也存在一些问题。 std::funcion
比较大,在 x64 中将占用 64 个字节,因此复制它不是最好的解决方案。您可以将其作为 const 引用传递,也可以作为 RAII 目的的 r 值引用传递。
#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, const std::array<double, 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.18, 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;
}
模板参数推导通过精确匹配您传入的参数来工作。它不考虑转换。
由于传递 MyFun
与传递函数指针相同,并且您的模板正在寻找 std::function
推导失败。
惯用的方法是接受模板中的任何可调用对象,而不用担心签名。由于您将在模板中调用该可调用对象,因此如果签名不匹配,您仍然会遇到编译时错误。
template <typename Func, size_t SIZE>
double MyFun(F f, std::array<double,SIZE> &x, std::array<double,SIZE> &y){
// go ahead and use f(x, y); for example
}
这种方法还有一个额外的好处,即您不限于一种类型的可调用对象。我们可以传入一个函数指针,一个 std::function,一个 Functor。任何支持语法 f(...);