为何C++中静态成员函数与静态lambda使用offsetof时行为不同?
C++中offsetof与不完全类型的编译差异问题
可正常编译的代码
#include <cstddef> struct A { char a; static constexpr int off(void) { return offsetof(A, a); } static constexpr int (*off_p)(void) = off; };
无法编译的lambda版本代码
#include <cstddef> struct A { char a; static constexpr int (*off_p)(void) = [](void) static constexpr ->int { return offsetof(A, a); }; };
编译报错信息
$ g++ -std=c++23 bad.cpp In file included from /usr/include/c++/13/cstddef:50, from bad.cpp:1: bad.cpp: In static member function ‘A::<lambda()> static’: bad.cpp:5:74: error: invalid use of incomplete type ‘struct A’
问题解答
1. 为何第一种使用不完全类型的情况被允许?
C++标准针对类成员函数定义中的offsetof使用有特殊规则:在类体内部定义成员函数时,即使类还未完全定义,只要offsetof的参数是当前类的成员,就可以合法调用。
原因在于,编译器处理成员函数off()的定义时,已经看到了成员a的声明,足以计算其偏移量;同时static constexpr函数是隐式内联的,它的实际实例化会推迟到类类型完全定义之后,此时A已是完整类型,offsetof的使用完全符合要求。
2. 为何第二种使用不完全类型的情况不被允许?
静态lambda的初始化逻辑和普通成员函数不同:lambda表达式的函数体在定义点会被立即解析,而非像成员函数那样延迟到类完全定义后处理。
在类体内部初始化静态成员off_p时,lambda的函数体被即时实例化,此时类A还处于不完全类型状态。C++标准并没有给lambda内部使用offsetof提供类似成员函数的例外,而offsetof要求操作的类型必须是完整类型,因此编译器判定这里属于“无效使用不完全类型”,触发报错。
内容的提问来源于stack exchange,提问作者stsp
相关产品推荐
相关产品推荐

