不同编译器下typeid操作类非静态成员的行为差异及原因分析
问题解答
编译器行为合规性判定
g的行为符合C标准,MSVC和Clang是默认启用了非标准扩展才允许原代码通过编译。
C++标准对非静态成员的指名表达式有明确限制:如果表达式中出现S::b这种直接指名非静态数据成员的写法,仅以下三种场景合法:
- 作为
.或->成员访问运算符的右操作数,例如s.b - 搭配取地址符构造成员指针,即
&S::b - 作为
decltype运算符的操作数
原代码中S::b直接作为typeid的操作数,不属于上述任何合法场景,因此属于语法错误,g的报错完全符合标准要求。如果给Clang编译时添加-pedantic-errors参数关闭非标准扩展,也会输出和g一致的错误。
修改后代码合法的原因
将代码修改为typeid(&S::b).name()后,操作数&S::b是合法的C++表达式,它生成一个指向类S的成员b的指针,类型为std::vector<std::string> S::*,完全满足typeid运算符对操作数的语法要求,因此可以正常编译运行,输出的就是该成员指针类型对应的名称。
内容的提问来源于stack exchange,提问作者mingyEx
相关产品推荐
相关产品推荐

