c++type-conversionstandardstype-safetystatic-cast

Why does static_cast not work as the cppref site says in such a case?


Consider the following code:

struct A {
    int    n;
    double d;
};

int main() {
    auto a = A{.n = 1, .d = 3.14};
    
    // error: static_cast from 'int*' to 'A*' is not allowed
    auto _ = static_cast<A*>(&a.n); 
}

See https://godbolt.org/z/8814sEh79

However, the documentation of static_cast in cppref says: (emphasis mine)

Two objects a and b are pointer-interconvertible if:

  • they are the same object, or
  • one is a union object and the other is a non-static data member of that object, or
  • one is a standard-layout class object and the other is the first non-static data member of that object or any base class subobject of that object, or
  • there exists an object c such that a and c are pointer-interconvertible, and c and b are pointer-interconvertible.

According to the citation above, &a and &a.n should be pointer-interconvertible, so why is static_cast<A*>(&a.n) ill-formed?


Solution

  • What you are referring to is §6.8.4 [basic.compound], paragraph 4:

    Two objects a and b are pointer-interconvertible if:

    [...]

    —(4.3) one is a standard-layout class object and the other is the first non-static data member of that object or

    [...]

    However, static_cast is not the tool for such a conversion, since for static_cast to work, the types need to be related. in your case, they are not. int is not related to A and vice versa. the only way you can achieve what you want is using a double static_cast over void* :

    static_cast<int*>(static_cast<void*>(a));

    which is equivalent to reinterpret_cast, which is the correct tool:

    If two objects are pointer-interconvertible, then they have the same address, and it is possible to obtain a pointer to one from a pointer to the other via a reinterpret_cast (7.6.1.10)