it-swarm.cn

为什么我不能在C++ 11中创建lambdas(相同类型)的向量?

我试图创建一个lambda矢量,但失败了:

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()>)'

我不想要一个函数指针向量或函数对象向量。但是,封装 real lambda表达式的函数对象向量对我有用。这可能吗?

82
Nawaz

每个lambda都有 不同的类型 - 即使它们具有相同的签名。如果要执行类似的操作,则必须使用运行时封装容器(如std::function)。

例如。:

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

所有lambda表达式都有不同的类型, 即使它们是逐个字符的相同 。你正在将一个不同类型的lambda(因为它是另一个表达式)推入向量中,这显然是行不通的。

一个解决方案 是制作std::function<int()>的向量。

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

另外,当你没有捕获任何东西时,使用[&]并不是一个好主意。

39
R. Martinho Fernandes

虽然其他人所说的是相关的,但仍然可以声明和使用lambda的向量,尽管它不是很有用:

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

所以,你可以在那里存储任意数量的lambda,只要它是lambda的复制/移动!

17
Luc Danton

如果你的lambda是无状态的,即[](...){...},C++ 11允许它降级为函数指针。理论上,符合C++ 11的编译器可以编译它:

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

每个lambda都是不同的类型。您必须使用std::Tuple而不是std::vector

3
Paul Fultz II

您可以使用lambda生成函数(使用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++;
    }
}

但我认为你现在基本上都是自己上课了。否则,如果lambda具有完全不同的caputres/args等,则可能必须使用元组。

2
antediluvian