编译时获取类成员变量地址为何触发C2327和C2065错误?
编译错误原因分析
问题描述
一段代码在VS2017的Hello World项目及其他应用中可正常编译,但移植到当前应用时出现编译错误。代码如下:
/** * This can be used to associate a class variable to a type and a string in order * to load it easily from XML or JSON. */ template<typename Class, typename T> struct Property { constexpr Property( T Class::*aMember, const char* aName ) : member { aMember }, name { aName } {} using Type = T; using ClassType = Class; T Class::*member; const char* name; }; struct MajorPaine { int mInt; // 所有错误都源于下面这行代码 static constexpr auto perp = Property<MajorPaine, decltype(MajorPaine::mInt)>{ &MajorPaine::mInt, "int" }; };
使用Microsoft (R) C/C++ Optimizing Compiler Version 19.16.27034 for x86编译时,报错如下:
error C2327: 'MajorPaine::mInt': is not a type name, static, or enumerator error C2065: 'mInt': undeclared identifier fatal error C1903: unable to recover from previous error(s); stopping compilation
错误原因及解决办法
核心原因:VS2017的19.16版本编译器存在bug,在类内部的静态成员初始化代码中,无法正确识别
decltype(MajorPaine::mInt)里的类成员。尽管mInt已经在类中声明,但编译器此时无法解析该成员引用,导致报错。而其他可正常编译的项目可能因启用了更高版本语言标准、编译器配置不同,或者使用了更新的编译器版本,避开了这个问题。解决办法:
- 利用模板自动推导:删除显式的模板参数,让编译器自动推导类型,修改后的代码如下:
这样编译器会自动识别static constexpr auto perp = Property{ &MajorPaine::mInt, "int" };Class为MajorPaine,T为int,绕开bug。 - 手动指定成员类型:将
decltype(MajorPaine::mInt)替换为成员的实际类型int,代码修改为:static constexpr auto perp = Property<MajorPaine, int>{ &MajorPaine::mInt, "int" }; - 升级编译器版本:若项目允许,将VS2017的编译器升级到19.20及以上版本,或直接升级到VS2019/VS2022,新版本编译器已修复该类内
decltype的识别问题。
- 利用模板自动推导:删除显式的模板参数,让编译器自动推导类型,修改后的代码如下:
内容的提问来源于stack exchange,提问作者Vaillancourt
相关产品推荐
相关产品推荐

