Почему я не могу создать вектор lambdas (одного типа) в С++ 11?

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

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

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

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

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

Ответ 1

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

например:

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

Ответ 4

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

auto ignore = []() { return 10; };  //1 note misssing & in []!
std::vector<int (*)()> v;     //2
v.push_back([]() { return 100; });  //3

Ответ 5

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

Ответ 6

Вы можете использовать функцию генерации лямбда (обновленную с помощью исправления, предложенной 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++;
    }
}

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