编译器差异:const成员函数内mutable lambda值捕获*this时this的类型
#include <type_traits> struct S { void f() const { (void)[*this]() mutable { static_assert( std::is_same_v<decltype(this), S *>); // GCC与MSVC下编译失败 static_assert( std::is_same_v<decltype(this), const S *>); // Clang下编译失败 (void)this; } (); } }; int main() {}
结论
Clang的实现符合现行C++标准规定,GCC与MSVC的行为属于尚未跟进标准缺陷修复的偏差。
规则依据与推导过程
- 基础背景
- 代码中
S::f是const限定成员函数,函数内的原始this指针类型为const S*,解引用得到的*this是const S&类型。 [*this]是C++17引入的按值捕获语法,语义是将当前*this对象拷贝一份,作为lambda闭包类型的非静态数据成员。
- 核心规则的标准修正
早期C17标准没有明确[*this]捕获场景下lambda体内this的解析规则,存在表述漏洞,后续C标准委员会核心工作组通过CWG Issue 2305完成了规则补全,明确规定:
当lambda使用
[*this]按值捕获当前类实例时,lambda体内所有对this的引用,都会被解析为指向捕获得到的实例副本的指针,而非外层成员函数的原始this指针。
- 结合本例推导
- 按值拷贝会剥离源对象的顶层const限定,因此捕获得到的副本本身是无cv限定的
S类型。 - 本例中lambda添加了
mutable修饰符,意味着lambda的operator()成员函数是无const限定的,访问闭包成员时不会附加const约束。 - 因此指向副本的
this指针类型为S*,与Clang的判定完全一致。
- GCC、MSVC行为的成因
这两款编译器目前尚未完整实现CWG 2305的决议,仍然将lambda体内的this错误解析为外层const成员函数的原始const S*指针,不符合现行C++标准的要求。
内容的提问来源于stack exchange,提问作者dfrib
相关产品推荐
相关产品推荐

