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

Naw*_*waz 83 c++ lambda vector c++11

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

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

直到第2行,它编译得很好.但第3行给出了编译错误:

错误:没有匹配函数来调用'std :: vector <main():: <lambda()>> :: push_back(main():: <lambda()>)'

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

Pup*_*ppy 129

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

例如:

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

  • 管理百人开发团队对我来说听起来更像是一场噩梦:) (52认同)
  • 另外,不要忘记无捕获的lambdas([] -style)可以降级为函数指针.所以他可以存储一组相同类型的函数指针.请注意,VC10尚未实现. (10认同)
  • 是否可以创建一个存储不同类型函数的向量?即不是将其限制为`std :: function <int()`,我可以使用不同的函数原型吗? (2认同)
  • @manatttta有什么意义?存在容器以存储相同类型的对象,以便一起组织和操纵它们.您不妨问'我可以创建一个存储`std :: function`和`std :: string`的`vector`吗?答案是一样的:不,因为那不是预期的用途.您可以使用'variant'样式类来执行足够的类型擦除以将不同的东西放入容器中,同时包括用户确定"真实"类型并因此选择如何处理的方法(例如,如何调用)每个元素......但又一次,为什么要这么长?有什么真正的理由吗? (2认同)

R. *_*des 39

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

一种解决方案是制作一个矢量std::function<int()>.

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

另一方面,[&]当你没有捕捉任何东西时,使用它并不是一个好主意.

  • 对于不带参数的lambdas,不需要`()`. (13认同)

Luc*_*ton 17

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

auto lambda = [] { return 10; };
std::vector<decltype(lambda)> vec;
vec.push_back(lambda);
Run Code Online (Sandbox Code Playgroud)

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

  • 不,你不把参数放在向量中,只是函数对象..所以它将是一个包含相同lambda的所有副本的向量 (7认同)

MSN*_*MSN 16

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

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

  • 对于记录`auto ignore =*[] {return 10; ``会使`ignore`成为`int(*)()`. (4认同)
  • 好吧,因为允许首先获取函数指针的转换函数被强制要求不是`explicit`,所以取消引用lambda表达式是有效的,并取消引用转换产生的指针.然后使用`auto`衰减引用回指针.(使用`auto&`或`auto &&`会保留引用.) (3认同)

ant*_*ian 5

您可以使用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++;
    }
}
Run Code Online (Sandbox Code Playgroud)

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