C++20模板Lambda表达式GCC可过,Clang/MSVC报错,是否合规?
该Lambda表达式是否符合C++20标准?
这段Lambda表达式能通过GCC编译,但被Clang和MSVC拒绝,它不符合C++20标准,具体原因及编译器反馈如下:
问题代码
static_assert([]<int I>() -> decltype([]<int = {I + I}>{ return true; }) { return {}; }.template operator()<{}>()());
编译器错误信息
Clang错误输出
<source>:14:48: error: expected expression 14 | static_assert([]<int I>() -> decltype([]<int = {I + I}>{ return true; }) | ^ <source>:15:40: error: expected expression 15 | { return {}; }.template operator()<{}>()()); |
MSVC错误输出
<source>(14): error C2065: 'I': undeclared identifier <source>(15): error C3889: call to object of class type '<lambda_1>': no matching call operator found <source>(14): note: could be 'auto <lambda_1>::operator ()(void) const' <source>(15): note: 'auto <lambda_1>::operator ()(void) const': could not deduce template argument for '_T1'
不符合标准的核心原因
内层Lambda无法引用外层Lambda的模板参数
C++20标准明确规定,Lambda模板参数默认值的作用域中,无法直接访问外层Lambda的模板参数I。内层Lambda的模板参数声明阶段,外层Lambda的I不属于其可见作用域,因此int = {I + I}的写法完全非法。GCC在此处做了非标准扩展支持,而Clang和MSVC严格遵循标准,因此报错。非法的模板operator()调用
外层Lambda的operator()本身并非模板函数(外层Lambda的模板参数I属于Lambda自身,而非operator()的模板参数),因此.template operator()<{}>的写法不符合语法——operator()没有模板参数列表,无法通过<>传递实参。GCC错误地接受了这个非法写法,而Clang/MSVC正确拒绝了不符合标准的调用方式。
内容的提问来源于stack exchange,提问作者303
相关产品推荐
相关产品推荐

