Как использовать шаблонный std :: function в качестве параметра? - PullRequest
0 голосов
/ 09 февраля 2020

Я хочу сделать for_each функцию для 2D-вектора, но есть ошибка:

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

Ответы [ 2 ]

5 голосов
/ 09 февраля 2020

Есть несколько решений. Я бы рекомендовал просто go для отдельного параметра шаблона для функции:

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

Проблема заключается в том, что компилятор не может определить VarType в function<void (VarType&)> из переданной лямбды. Таким образом:

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

также будет работать, так как этот тип (int&) уже известен.

PS В C ++ 17 вы можете сделать std::function action = [](int &val) { val = 1; };.

2 голосов
/ 09 февраля 2020

Хотя я считаю, что использование функции в качестве другого параметра шаблона, предложенного @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<...>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...