使用gcc 4.9 -std = c ++ 14,我尝试制作一个lambdas矢量:
vector<function<void ()>> v = {[]{cout << "foo";}, []{cout << "bar";}};
for (auto&& a: v) a();
它运作得很好。然后我尝试将lambdas的初始化列表直接传递给基于范围:
for (auto&& a: {[]{cout << "foo";}, []{cout << "bar";}}) a();
我得到了:
error: unable to deduce 'std::initializer_list<auto>&&' from '{<lambda closure object>main()::<lambda()>{}, <lambda closure object>main()::<lambda()>{}}'
根据错误消息的外观判断,我猜测它可能是因为&#34; lambda闭包对象&#34; s是内置语言术语,而不是直接等价的std :: function(所以没有真正的类型)。
这是什么原因?此外,这可能与实现相关,还是由规范决定的行为?
答案 0 :(得分:6)
每个lambda都有自己独特的类型。所以你可能不会从不同类型的lambdas构建std :: initializer_list。
根据C ++标准(5.1.2 Lambda表达式)
3 lambda表达式的类型(也是的类型 closure object)是一个独特的,未命名的nonunion类类型 - 称为 闭包类型 - 其属性如下所述。
另外
6非泛型lambda表达式的闭包类型,没有 lambda-capture有一个公共的非虚拟非显式const转换 函数指向函数与C ++语言链接(7.5)有 与闭包类型的函数相同的参数和返回类型 呼叫运营商。
答案 1 :(得分:6)
每个lamdba都有自己的类型,因此编译器无法推断出initializer_list
的类型。
你必须告诉你想要哪种类型:
对于每个lambda:
由于你的lambda没有捕获变量,你可以将它们衰减为指向+
的函数,如下所示:
for (auto&& a: {+[]{std::cout << "foo";}, +[]{std::cout << "bar";}}) a();
使用function<void()>
:
for (auto&& a: {std::function<void()>([]{std::cout << "foo";}),
std::function<void()>([]{std::cout << "bar";})}) a();
对于initializer_list:
for (auto&& a: std::initializer_list<std::function<void()>>{
[]{std::cout << "foo";},
[]{std::cout << "bar";}}) a();
答案 2 :(得分:0)
每个lambda都是不相关的类型。碰巧的是,它们都可以转换为std::function<void()>
,但这是因为std::function
会声称转换任何内容,并且当它们可以通过void()
签名并且可复制和可破坏时可以使用它
在vector
的情况下,有一个std::initializer_list<std::function<void()>>
构造函数从构造函数列表中考虑。这是匹配,尝试和编译。
如果没有该参数(vector ctor的list参数)匹配,{}
语法会在其内容中查找公共类型。没有共同的类型,所以它失败了。
该语言不会搜索每个类型和模板,以便在两个(不相关的)lambdas之间找到可能的公共类型。它不会读你的想法。
你可以这样做:
using nullary = std::function<void()>;
template<class T>
using il=std::initializer_list<T>;
for(auto f:il<nullary>{[]{ std::cout<<"hello";},[]{std::cout<<" world\n";}}){
f();
}
答案 3 :(得分:0)
我学习here的一个技巧是使用追溯演员。所以有了这样一个工具:
template<typename T>
struct memfun_type
{
using type = void;
};
template<typename Ret, typename Class, typename... Args>
struct memfun_type<Ret(Class::*)(Args...) const>
{
using type = std::function<Ret(Args...)>;
};
template<typename F>
typename memfun_type<decltype(&F::operator())>::type
FFL(F const &func)
{ // Function from lambda !
return func;
}
你could write这样的事情
vector<function<void()>> v = { FFL([]{cout << "foo"; }), FFL([]{cout << "bar"; }) };
for (auto&& a : v) a();