简体   繁体   中英

How to use templated std::function as parameter?

I want to make for_each function for 2D-vector but there is an error:

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. 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.

PS In C++17 you can do 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:


If you want VarType to be deduced from the first function parameter, then you can make the second parameter a non-deduced context:

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:

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<...> .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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