请注意,[class.mem] p6中未提及trailing-return-type
一个完整的类的上下文是一个
(6.1)函数体,
(6.2)默认参数,
(6.3)noexcept-specifier([except.spec]),
(6.4)合同条件,或
(6.5)默认成员初始化程序在类的成员规范内.[注意:如果嵌套类在封闭类的成员规范中定义,则嵌套类的完整类上下文也是任何封闭类的完整类上下文. - 结束说明]
[expr.prim.this] p2也有关于此的说明:
如果声明声明了类X的成员函数或成员函数模板,则表达式是可选的cv-qualifier-seq和函数定义结尾之间的类型为"指向cv-qualifier-seq X的指针"的prvalue ,成员声明者或声明者.它不应出现在可选的cv-qualifier-seq之前,它不应出现在静态成员函数的声明中(尽管它的类型和值类别是在静态成员函数中定义的,因为它们在非静态成员函数中) .[注意:这是因为声明匹配在完整声明符已知之前不会发生.- 尾注] [注意:在trailing-return-type中,为了类成员访问的目的,要求定义的类不需要完整.稍后声明的类成员不可见.[例子:......
struct Test{
Test show(){
return Test{};
}
int a;
};
Run Code Online (Sandbox Code Playgroud)
考虑上面的代码,函数的返回类型应该是完整类型,因为:
dcl.fct#11
不得在返回类型或参数类型中定义类型。函数定义的参数类型或返回类型在函数定义的上下文中不应是不完整的(可能是 cv 限定的)类类型,除非删除该函数。
该类型Test用作函数的返回类型show,该类型在 class 的定义中定义Test。然而,根据标准,Test此时类类型被视为不完整类型,因为:
class.mem#6
在类说明符的结尾 } 处,类被视为完全定义的对象类型 ([basic.types])(或完整类型)。在类成员规范中,类在函数体、默认参数、noexcept 说明符和默认成员初始值设定项(包括嵌套类中的此类内容)中被视为完整。否则,它在其自己的类成员规范中被视为不完整。
成员函数 show 不是deleted,它是在 class 的定义中定义的Test。这return type句话并没有满足我所强调的内容。此时,返回类型应为不完整类型。然而编译器认为代码格式良好
作为反面:
struct B;
struct Test{
B show(){
}
int a;
};
Run Code Online (Sandbox Code Playgroud)
编译器将给出明确的错误
通知,表示返回类型B不完整。这是符合规则的。
为什么编译器将第一个示例视为格式良好的代码?这是一个错误吗?如果我遗漏了有关此类情况的任何特殊规则,请指出。