You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于Lambda捕获实体的decltype(),哪款编译器符合ISO C++17标准?

Lambda捕获与decltype的编译器合规性分析

测试代码

#include <iostream>
#include <type_traits>

int main(){

    int i = 1;
    int& j = i;

    auto f2 = [j = j]() {
        std::cout
            << std::is_same_v<decltype(j), int&>
            << std::is_same_v<decltype((j)), int&>
            << std::is_same_v<decltype((j)), const int&>;
    };
    
    auto f3 = [=]() {
        std::cout
            << std::is_same_v<decltype(j), int&>
            << std::is_same_v<decltype((j)), int&>
            << std::is_same_v<decltype((j)), const int&>;
    };

    f2();
    f3();
}

C++17下各编译器输出

gccclangmsvc
001001010
110101101

标准规则与合规性判断

1. 初始化捕获f2 = [j = j]()的分析

根据C++17标准:

  • 初始化捕获[j = j]等价于auto j = j,外部的j是int&类型,auto推导会忽略引用,因此Lambda闭包的成员j类型为int。
  • Lambda的operator()默认是const成员函数,因此闭包成员j在函数体内是const左值。
    • decltype(j):取变量本身的类型,结果为int,因此第一个输出为0。
    • decltype((j)):带括号的表达式是const左值,类型为const int&,因此第二个输出为0,第三个输出为1。
  • 合规结论:f2的正确输出是001,gcc和clang符合标准,msvc输出010不符合标准。

2. 值捕获f3 = [=]()的分析

根据C++17标准:

  • 值捕获引用变量j时,闭包的成员类型为被引用的类型(即int),而非引用类型。Lambda内部的j是该成员的名字,类型为int。
  • 同样,operator()是const成员函数,成员j在函数体内是const左值。
    • decltype(j):变量类型为int,第一个输出应为0。
    • decltype((j)):表达式类型为const int&,第二个输出应为0,第三个输出应为1。
  • 合规结论:f3的正确输出应为001,但三款编译器的输出均不符合此结果,说明三款编译器在值捕获引用变量的decltype处理上均存在错误。

总结

  • 对于初始化捕获场景,gcc和clang符合C++17标准,msvc存在错误。
  • 对于值捕获引用变量的场景,三款编译器均不符合C++17标准。

内容的提问来源于stack exchange,提问作者余国良

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 15:48:07