通过类型别名定义的析构器:GCC/Clang编译分歧谁符合C++标准?
问题描述
以下代码在GCC 14.2及之前版本可正常编译,但从Clang 11开始被拒绝(Clang 10可正常编译),其中仅析构函数的定义被拒绝。请问哪个编译器的行为符合C++标准?能否引用标准具体条款说明?
struct Inner{ Inner(); ~Inner(); }; struct Outer { using Inner = ::Inner; }; Outer::Inner::Inner() { // } Outer::Inner::~Inner() { // }
解答
Clang 11及之后版本的行为符合C++标准,GCC的处理不符合标准要求。
标准条款依据
根据C++17及后续版本的标准中**[namespace.qual](命名空间限定查找)和[class.mfct]**(成员函数定义)的相关规则:
在类外部定义成员函数时,必须使用类的真实作用域来限定函数名,不能通过另一个类中
using声明引入的类别名来限定——除非该别名指向的是当前类的基类成员。
在上述代码中,Outer::Inner只是全局命名空间里Inner类的别名,并非Outer的基类成员。因此,Outer::Inner::~Inner()这种写法违反了标准:编译器会将其解析为尝试定义Outer::Inner对应类的析构函数,但标准禁止通过非基类成员的别名进行跨作用域的成员函数定义。
至于构造函数Outer::Inner::Inner()能被GCC和旧版Clang接受,是因为这些编译器在此处没有严格执行标准规则,实际上这种写法同样不符合标准。Clang 11开始严格执行标准,而析构函数的名称依赖于类名的特殊语法,使得编译器更容易检测到这种违规,因此首先对析构函数的定义进行了正确拒绝。
正确的写法应直接使用类的真实作用域:
Inner::Inner() { // } Inner::~Inner() { // }
内容的提问来源于stack exchange,提问作者Bulletmagnet
相关产品推荐
相关产品推荐

