简体   繁体   English

如何使用模板化 std::function 作为参数?

[英]How to use templated std::function as parameter?

I want to make for_each function for 2D-vector but there is an error:我想为 2D-vector 制作for_each函数,但有一个错误:

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

How can I fix it?我该如何解决?

#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;
    });
}

There are a few solutions.有几种解决方案。 I would recommend to just go for a separate template parameter for the function:我建议只为该函数使用一个单独的模板参数:

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

The problem is that the compiler cannot figure out the VarType in function<void (VarType&)> from the passed lambda.的问题是,编译器不能弄清楚VarTypefunction<void (VarType&)>从传递拉姆达。 So doing:这样做:

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

would also work, since this way the type ( int& ) is already known.也可以工作,因为这样类型 ( int& ) 是已知的。

PS In C++17 you can do std::function action = [](int &val) { val = 1; }; PS 在 C++17 中你可以做std::function action = [](int &val) { val = 1; }; std::function action = [](int &val) { val = 1; }; . .

While I think taking the function as another template parameter as suggested by @DeiDei is the better solution, here is an alternative:虽然我认为将函数作为@DeiDei 建议的另一个模板参数是更好的解决方案,但这里有一个替代方案:


If you want VarType to be deduced from the first function parameter, then you can make the second parameter a non-deduced context:如果您希望从第一个函数参数推导出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);
        }
    }
}

This requires C++20 for std::type_identity and #include<type_traits> , but you can implement your own type_identity easily:这需要 C++20 用于std::type_identity#include<type_traits> ,但您可以轻松实现自己的type_identity

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

This works because everything left to the scope resolution operator :: is a non-deduced context, meaning that the template parameters in it will not be deduced from this function parameter.这是有效的,因为留给作用域解析运算符::都是非推导的上下文,这意味着其中的模板参数不会从此函数参数推导。 Your original function fails template argument deduction, because VarType cannot be deduced from the second parameter as the second function argument given in the call does not actually have type std::function<...> .您的原始函数未能通过模板参数推导,因为无法从第二个参数推导出VarType ,因为调用中给出的第二个函数参数实际上没有类型std::function<...>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM