Почему я не могу создать вектор лямбд (того же типа) в C ++ 11? - PullRequest
83 голосов
/ 20 сентября 2011

Я пытался создать вектор лямбды, но не смог:

auto ignore = [&]() { return 10; };  //1
std::vector<decltype(ignore)> v;     //2
v.push_back([&]() { return 100; });  //3

До строки # 2 он прекрасно компилируется .Но строка # 3 дает ошибку компиляции :

ошибка: нет соответствующей функции для вызова 'std :: vector> :: push_back (основной () ::) '

Мне не нужен вектор указателей на функции или вектор функциональных объектов.Однако вектор функциональных объектов, которые инкапсулируют real лямбда-выражения, будет работать для меня.Это возможно?

Ответы [ 6 ]

127 голосов
/ 20 сентября 2011

Каждая лямбда имеет различного типа - даже если они имеют одинаковую подпись. Вы должны использовать инкапсулирующий контейнер во время выполнения, такой как std::function, если вы хотите сделать что-то подобное.

например:.

std::vector<std::function<int()>> functors;
functors.push_back([&] { return 100; });
functors.push_back([&] { return  10; });
39 голосов
/ 20 сентября 2011

Все лямбда-выражения имеют различный тип, , даже если они идентичны посимвольно .Вы вставляете лямбду другого типа (потому что это другое выражение) в вектор, и это, очевидно, не сработает.

Одно из решений - сделать вектор равным std::function<int()> вместо этого.

auto ignore = [&]() { return 10; };
std::vector<std::function<int()>> v;
v.push_back(ignore);
v.push_back([&]() { return 100; });

С другой стороны, не рекомендуется использовать [&], когда вы ничего не захватываете.

17 голосов
/ 20 сентября 2011

Хотя то, что сказали другие, уместно, все еще можно объявить и использовать вектор лямбда, хотя это не очень полезно:

auto lambda = [] { return 10; };
std::vector<decltype(lambda)> vector;
vector.push_back(lambda);

Таким образом, вы можете хранить там любое количество лямбд, если это копия / ход lambda!

15 голосов
/ 20 сентября 2011

Если ваша лямбда не имеет состояния, то есть [](...){...}, C ++ 11 позволяет ей превращаться в указатель на функцию.Теоретически, совместимый с C ++ 11 компилятор мог бы скомпилировать это:

auto ignore = []() { return 10; };  //1 note misssing & in []!
std::vector<int (*)()> v;     //2
v.push_back([]() { return 100; });  //3
3 голосов
/ 22 февраля 2013

Каждая лямбда - это другой тип. Вы должны использовать std::tuple вместо std::vector.

2 голосов
/ 28 июля 2016

Вы можете использовать лямбда-генерирующую функцию (обновлено с исправлением, предложенным Nawaz):

#include <vector>
#include <iostream>

int main() {
    auto lambda_gen = [] (int i) {return [i](int x){ return i*x;};} ;

    using my_lambda = decltype(lambda_gen(1));

    std::vector<my_lambda> vec;

    for(int i = 0; i < 10; i++) vec.push_back(lambda_gen(i));

    int i = 0;

    for (auto& lambda : vec){
        std::cout << lambda(i) << std::endl;
        i++;
    }
}

Но я думаю, что на этом этапе вы создали собственный класс.В противном случае, если лямбды имеют совершенно разные caputres / args и т. Д., Вам, вероятно, придется использовать кортеж.

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