这看起来类似于"I cannot pass lambda as std::function",但实际上我是通过值传递std::function参数,因此该问题不适用。我定义了以下函数。

template<typename T>
std::vector<T> countSort(const std::vector<T> &v, std::function<int(T)> keyFunc, int n);
第二个参数是std::function,它将T映射到int(按值传递)。
调用此函数时,我想使用一个lambda表达式,如下所示:
std::vector<int> v;
[...]
v = countSort(v, [](int x) { return x; }, 10);
但是模板参数推导失败,因为“main()::<lambda(int)>不是从std::function<int(T)>派生的”。如果我指定了模板参数,或者为lambda表达式引入了std::function类型的中间变量,它就会起作用:
std::function<int(int)> lambda = [](int x) { return x; };
v = countSort(v, lambda, 10);
我为什么不能做前者?我给编译器完全相同的信息。如果在将变量分配给变量时能够将lambda<int>类型的值转换为std::function<int(int)>,为什么不能直接将lambda<int>转换为参数类型std::function<T(int)>,并考虑到v的类型为std::vector<int>,应该知道Tint吗?我想使用lambda表达式的全部原因就是它是一个表达式,因此我应该能够在函数调用参数列表中内联编写它,而不必给它起一个名称或将其分配给一个变量。

最佳答案

问题是,template argument deduction不考虑隐式转换(从lambda到std::function),这会导致对第二个函数参数T上的keyFunc的推论失败。

您可以使用 std::type_identity (自C++ 20起)从推论中排除第二个函数参数。例如

template<typename T>
std::vector<T> countSort(const std::vector<T> &v, std::function<int(std::type_identity_t<T>)> keyFunc, int n);

顺便说一句:如果您的编译器不支持std::type_identity,创建它并不难。
有关std::type_identity在这里的工作方式,请参见non-deduced context:
(强调我的)

关于c++ - 将lambda参数传递给没有中间变量的std::function参数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/63558068/

10-13 09:09
查看更多