【问题标题】:How to declare a vector of functions (lambdas)如何声明函数向量(lambdas)
【发布时间】:2016-11-22 07:43:29
【问题描述】:

我已经了解了如何声明函数向量(请参阅calling a function from a vector)。

但是那回答用户指针。如何使用现代 C++ 中的新语法创建函数/lambda 向量?

使用新语法的函数示例通常使用 auto:

auto f = [] (std::string msg) -> void { 
    std::cout << msg << std::endl;
};

f 的实际类型是什么?那么我可以声明一个这种类型的向量吗?

非常感谢您的帮助

【问题讨论】:

  • "f 的实际类型是什么?" 无法命名。 “所以我可以声明这种类型的向量?” 是的,但这无济于事,因为 lambdas 不是默认可构造的。 std::vector&lt;std::function&lt;void(std::string)&gt;&gt; 可能适合您的目的。
  • 如果 lambda 没有闭包,你实际上仍然可以使用指针,顺便说一句
  • 如果您不需要向量(即,如果实际的 lambda 在编译时已知),您可以创建一个 std::tuple 的 lambda。

标签: c++ c++11 c++14


【解决方案1】:

std::function与对应的类型一起使用:

std::vector<std::function<void(void)>> vec;
vec.push_back([]()->void{});

在你的情况下是std::function&lt;void(std::string)&gt;

根据标准 ([expr.prim.lambda]/3),lambda 的确切类型没有意义:

lambda 表达式的类型(也是闭包对象的类型)是唯一的、未命名的非联合类类型

【讨论】:

  • 谢谢。这正是我想要的。
  • 另一个选项是使用函数指针,如果 lambdas 没有捕获。
【解决方案2】:

f 的实际类型是什么?那么我可以声明一个这种类型的向量吗?

f 的类型只能使用auto 来推断。您可以使用

声明此类型的vector
std::vector<decltype(f)> v;

但是,它不是很有用。看起来非常相似的 Lambda 函数有不同的类型。更糟糕的是,具有相同主体的 lambda 函数也有不同的类型。

auto f = [] (std::string msg) -> void { 
    std::cout << msg << std::endl;
};

auto g = [] (std::string msg) -> void { 
    std::cout << msg << std::endl;
};

auto h = [] (std::string msg) -> void { 
    std::cout << msg << '+' << msg << std::endl;
};

鉴于上述功能,你不能使用

std::vector<decltype(f)> v;
v.push_back(f);  // OK
v.push_back(g);  // Not OK
v.push_back(h);  // Not OK

您最好的选择是创建一个std::vectorstd::functions。您可以将 lambda 函数添​​加到该 std::vector。鉴于上述fg 的定义,您可以使用:

std::vector<std::function<void(std::string)>> v;
v.push_back(f);
v.push_back(g);
v.push_back(h);

【讨论】:

    【解决方案3】:

    如前所述,您声明的每个 lambda 具有唯一的特定于上下文的类型,即使它具有看似相同的签名。这就是为什么 lambda 向量仅具有理论值的原因-您最多只能推到一个 lambda ...您有两种选择-您可以采用其他答案中提出的方法并将 lambda 存储到类型擦除 @987654322 @ 在将它们放入向量或将您的 lambda 放入“容器”之前,该容器将收集除 lambda 对象本身之外的每个元素的类型 - std::tuple

    auto t = std::make_tuple([](){ std::cout<<"First lambda" << std::endl; },
                             [](){ std::cout<<"Second lambda"<< std::endl; },
                             [](){ std::cout<<"Third lambda" << std::endl; });
    

    并在编译时获得适当的 lambda:

    std::get<0>(t)(); // the value in get must be known at compile time! 
                      // otherwise compiler won't be able to establish type 
                      // of lambda and the whole point of using tuple is lost
    

    [live demo]

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-24
      • 2017-01-26
      • 1970-01-01
      • 2014-01-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多