按值捕获引用的Lambda内部变量类型判定及编译器差异问题
C++ Lambda按值捕获引用参数的类型争议
template <typename> struct TD; void foo(int &par) { auto l = [par]() { TD<decltype(par)>(); }; }
这段代码故意不编译,利用未定义的模板TD触发编译器报错,以此展示lambda内部par的类型——这里par是按值捕获的。
不同编译器的行为差异
GCC和Clang的报错信息显示lambda内部
par的类型为int&::5:9: error: implicit instantiation of undefined template 'TD ' MSVC在默认旧标准下报错显示类型为
int:(5): error C2027: use of undefined type 'TD '
将MSVC切换到C++20标准后,报错也会显示类型为int&。
标准规定
当前C++标准草案对lambda按值捕获的成员类型有明确规则:对于每个按副本捕获的实体,闭包类型中会声明一个未命名的非静态数据成员。该成员的类型遵循以下规则:
- 若捕获的实体是对象引用,则成员类型为被引用的类型;
- 若捕获的实体是函数引用,则成员类型为被引用函数类型的左值引用;
- 其他情况则为捕获实体的类型。
核心疑问
- 哪个编译器的行为是正确的?
- C++标准是否有过相关变更?
- 如果按标准
par应该是引用类型,原因是什么?根据上述标准文本,用户认为par的类型应该是被引用类型int。
另外有一个细节:打印foo函数中par和lambda内部par的地址,二者并不相同,说明编译器确实对par进行了复制,但为什么lambda内部的par会被推导为引用类型?是不是编译器创建了par的匿名副本后,又将其绑定到了一个非const引用上?
内容的提问来源于stack exchange,提问作者geza
相关产品推荐
相关产品推荐

