为什么这段代码有C2784"无法推断模板参数"错误

ath*_*hos 5 c++ lambda templates function-pointers

作为参数传递的Lambda函数我可以编译示例:

template <class Range>
Range FindFirstIf(Range, bool(*Function)(typename Range::ConstReference value));

struct range {  using ConstReference = const float&; };

range rng;
rng = FindFirstIf(rng, [](const float& val) { return (val < 0.0f); });
Run Code Online (Sandbox Code Playgroud)

当然它无法链接,因为FindFirstIf没有实现.

但是,当我做了类似的事情:

template <class Range, class ValueType>
Range MyTest(Range, ValueType, bool(*Function)(ValueType value));

std::vector <int> vi;
double d = 0;
vi =       MyTest(vi, d, [](double val) { return (val < 0.0f); });
Run Code Online (Sandbox Code Playgroud)

它有编译错误:

错误C2784:'Range MyTest(Range,ValueType,bool(__ cdecl*)(ValueType))':无法从'main ::'推断'bool(__ cdecl*)(ValueType)'的模板参数

为什么这样?我想通过传入d,ValueType可以推断为double

sky*_*ack 3

改用它(注意+):

vi = MyTest(vi, d, +[](double val) { return (val < 0.0f); });
Run Code Online (Sandbox Code Playgroud)

在某些情况下,Lambda 函数可以衰减为函数指针,但它们本身并不是函数指针。
换句话说,推导失败,因为它期望在函数指针上工作,但 lambda 不是函数指针,它当然可以转换,但首先必须进行推导,但不能,因为 lambda 不是函数指针预期类型,它可能会衰减到它......等等。通过在 lambda 前面
添加,可以在将其传递给函数之前强制进行转换,从而按预期接收实际的函数指针并继续进行推导。+MyTest

这是一个基于您的代码的最小工作示例:

#include<vector>

template <class Range, class ValueType>
Range MyTest(Range, ValueType, bool(*Function)(ValueType value)) {}

int main() {
    std::vector <int> vi;
    double d = 0;
    vi = MyTest(vi, d, +[](double val) { return (val < 0.0f); });
}
Run Code Online (Sandbox Code Playgroud)