GCC修改const&限定成员函数指针ref限定符问题的标准合规性问询
编译行为差异现象
以下代码片段可在Clang中正常编译,但无法通过GCC 12版本编译:
// function type (c style) //typedef int fun_type() const&; // C++ style using fun_type = int() const&; struct S { fun_type fun; }; int S::fun() const& { return 0; } int main() { fun_type S::* f = &S::fun; }
GCC编译时抛出如下错误信息:
prog.cc: In function 'int main()': prog.cc:21:25: error: cannot convert 'int (S::*)() const &' to 'int (S::*)() const' in initialization 21 | fun_type S::* f = &S::fun; | ^~~~~~~
按照C++语法规则,上述代码中结构体S的声明理应等价于如下写法:
struct S { int fun() const&; };
即便直接使用该等价声明替换原有定义,两个编译器的行为也不会发生变化。
判定结论
这是GCC 12版本的实现Bug,Clang的处理完全符合C++标准规范。
C++标准明确规定:使用带cv限定符、引用限定符的函数类型别名声明类成员函数时,别名携带的所有限定符都会完整作用于该成员函数的最终类型。上述代码里fun_type的定义是int() const&,那么类内fun_type fun;声明出的成员函数类型就是int (S::)() const&,对应取地址得到的成员指针类型自然是int (S::*)() const&,和fun_type S::*的类型完全匹配,不需要做任何类型转换,初始化行为完全合法。
GCC 12的错误来源于实现缺陷:它在处理这类带引用限定符的函数类型别名时,在成员指针类型推导阶段错误丢弃了引用限定符,把目标类型错判为不带&限定的int (S::*)() const,才抛出了类型不匹配的错误。该Bug在GCC 13及之后的版本中已经完成修复。
内容的提问来源于stack exchange,提问作者Swift - Friday Pie
相关产品推荐
相关产品推荐

