我正在尝试使用lambdas和编译器,因为another question就在这里 我刚刚意识到(并且确实非常正常)以下代码是有效的:
int main() {
auto l = [](){};
l.operator()();
}
实际上标准说闭包类型有一个公共内联函数调用操作符等等,因此能够调用它是有意义的。
通过查看标准(以及工作草案)我无法解释的事实是GCC(6.1)编译了以下片段(clang 3.9没有):
int main() {
auto l = []<typename>(){};
l.operator()<void>();
}
没有警告,没有错误。它是有效的代码还是被编译器拒绝?
答案 0 :(得分:21)
在N4140 5.1.2 [expr.prim.lambda]中,Lambda表达式定义为
lambda-introducer lambda-declarator opt compound-statement
其中&#34; lambda-introductioncer&#34; 是[]
,包含一个可选的&#34; lambda-capture&#34; 和&#34; lambda-declarator opt &#34; 是以&#34;(parameter-declaration-clause)&#34;开头的东西。
[]<typename>(){}
不符合该要求,因为lambda介绍器和lambda声明符之间存在某些内容,因此它不是有效的lambda表达式。
因此,您的示例代码不是有效的C ++,应该被编译器拒绝。
由于此标记为gcc,因此我点击了GNU C++ extensions列表。我没有找到任何可以使GNU C ++中的语法合法的扩展。
然而,根据this proposal(P0428R0)的第4节,它建议将模板化的lambdas添加到C ++中,gcc在2009年得到了上述论文的实验性实现。这可能解释了为什么gcc不能解决这个问题。抱怨在这里。
答案 1 :(得分:2)
它似乎是一个GCC扩展(模板化的lambdas)。
#include <iostream>
int main() {
auto l = []<typename T>(T const& x){ std::cout << __PRETTY_FUNCTION__ << " " << x << std::endl;};
l(42);
l("Hello world");
}
结果
main()::<lambda(const T&)> [with T = int] 42
main()::<lambda(const T&)> [with T = char [12]] Hello world
答案 2 :(得分:0)
自C ++ 20起,给定的代码格式正确,并且可以正常工作。
lambda-expression :
lambda-introducer lambda-declarator opt 复合语句
lambda简介<
template-parameter-list>
需要子句 opt lambda声明符 opt 复合语句 < / p>
最后一行反映了这种语法。根据{{3}}:
如果存在 decl-specifier ,则lambda是通用lambda decl-specifier-seq 中的 placeholder-type-specifier lambda-expression 的 parameter-declaration ,,或者lambda具有 template-parameter-list 。 < / p>