Why are we allowed to take the address of an incom

2020-08-19 05:01发布

Consider this code:

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

Why does C++ allow taking the address of an incomplete reference type?

Couldn't it be potentially illegal, as shown above? Is this intentional?

1条回答
【Aperson】
2楼-- · 2020-08-19 06:01

Yes, that's intentional, and the possibility of breakage if operator& is overloaded is known.

Taking the address of incomplete types has been possible since long before C++. In C, there is absolutely no risk of any breakage, because & cannot be overloaded.

C++ chose not to unnecessarily break previously valid programs, and simply specified that if an incomplete type does turn out to have an overloaded & operator, it's unspecified whether the overloaded operator gets used.

Quoting N4140:

5.3.1 Unary operators [expr.unary.op]

If & is applied to an lvalue of incomplete class type and the complete type declares operator&(), it is unspecified whether the operator has the built-in meaning or the operator function is called.

This can be interpreted to apply even to a class currently being declared, and even when a declaration of operator& has already been seen:

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
}

Here, GCC gives m type A * and rejects the program, but clang gives it type int and accepts it.

查看更多
登录 后发表回答