为什么我们允许采用不完整类型的地址?

Meh*_*dad 10 c++ reference incomplete-type

考虑以下代码:

class Addressable;
class Class1  { void foo(Addressable &a) { (void) &a; } };  // OK
class Addressable { void *operator &() { return this; } };
class Class2  { void foo(Addressable &a) { (void) &a; } };  // Error: operator & private
Run Code Online (Sandbox Code Playgroud)

为什么C++允许获取不完整引用类型的地址?

如上所示,它不可能是非法的吗?这是故意的吗?

小智 5

是的,这是故意的,如果operator&超载则可能发生破损.

在C++之前很久就采用不完整类型的地址.在C中,绝对没有任何破损的风险,因为&不能超载.

C++选择不会不必要地破坏以前有效的程序,并且只是指定如果一个不完整的类型确实有一个重载的&运算符,则未指定是否使用了重载的运算符.

引用N4140:

5.3.1一元运算符[expr.unary.op]

如果&应用于不完整类类型的左值并且完整类型声明operator&(),则未指定运算符是否具有内置含义或是否调用了运算符函数.

这可以解释为甚至适用于当前正在声明的类,即使operator&已经看到声明:

extern struct A a;
struct A {
  int operator&();
  decltype(&a) m; // int, or A *?
};
int main() {
  return A().m; // only valid if m is int
}
Run Code Online (Sandbox Code Playgroud)

在这里,GCC提供m类型A *并拒绝该程序,但clang给它类型int并接受它.