如何使用模板化标准::函数作为参数?

How to use templated std::function as parameter?

本文关键字:函数 参数 标准 何使用      更新时间:2023-10-16

我想为 2D 矢量制作for_each函数,但有一个错误:

error: no matching function for call to ‘each(std::vector<std::vector<int> >&, main()::<lambda(int&)>)’

我该如何解决它?

#include <iostream>
#include <vector>
#include <functional>
using namespace std;
template <class VarType>
void each(vector<vector<VarType>> &ve, function<void (VarType &)> action) {
for(vector<VarType> &v : ve) {
for(VarType &p : v) {
action(p);
}
}
}
int main() {
vector<vector<int>> map(5);
for(vector<int> &ve : map) {
ve.resize(4);
}
each(map, [](int &val) {
val = 1;
});
}

有几种解决方案。我建议只为函数使用单独的模板参数:

template <class VarType, class Function>
void each(vector<vector<VarType>> &ve, Function action) {
// no more worries
}

问题是编译器无法从传递的 lambda 中找出function<void (VarType&)>中的VarType。这样做:

function<void(int&)> action = [](int &val) {
val = 1;
};
each(map, action);

也可以工作,因为这样类型(int&(是已知的。

附言在 C++17 中,您可以执行std::function action = [](int &val) { val = 1; };.

虽然我认为按照@DeiDei的建议将该函数作为另一个模板参数是更好的解决方案,但这里有一个替代方案:


如果您希望从第一个函数参数推导VarType,则可以将第二个参数设置为非推导上下文:

template <class VarType>
void each(vector<vector<VarType>> &ve,
typename type_identity<function<void (VarType &)>>::type action) {
for(vector<VarType> &v : ve) {
for(VarType &p : v) {
action(p);
}
}
}

这需要 C++20 用于std::type_identity#include<type_traits>,但您可以轻松实现自己的type_identity

template<typename T>
struct type_identity {
using type = T;
};

这是有效的,因为留给范围解析运算符的所有内容都是非推导上下文::这意味着其中的模板参数不会从此函数参数中推导出来。您的原始函数无法推断模板参数,因为无法从第二个参数推断VarType因为调用中给出的第二个函数参数实际上没有类型std::function<...>