c++language-lawyerfunction-pointersvoid-pointersstatic-cast

Why can't I static_cast a void* to a pointer-to-function?


This can be compiled (despite being UB (right?) because fvp == nullptr)

int f;
void* fvp{};
decltype(f)* fp = static_cast<decltype(f)*>(fvp);

but this cannot

void f() {}
void* fvp{};
decltype(f)* fp = static_cast<decltype(f)*>(fvp);

because (Clang says)

Static_cast from 'void *' to 'decltype(f) *' (aka 'void (*)()') is not allowed [bad_cxx_cast_generic]

Why is this the case? And where from the standard do I understand this? I guess [expr.static.cast] is where I should look at; specifically 7, but I'm not sure.


Follow up question on the reason why I wanted to ask this one.


Solution

  • This is not allowed because [expr.static_cast] does not allow it. Indeed, the relevant language is:

    No other conversion shall be performed explicitly using a static_­cast.

    Since there is no conversion listed that would permit conversion from void* to a function pointer type, that conversion is not allowed.

    The rationale is that function and data pointers may have different sizes or alignment requirements.

    You might consider a reinterpret_cast, which conditionally supports such conversions. But it would be better to use a design that does not require such conversions. If you need to type-erase a function pointer, you will still need reinterpret_cast but can use e.g. void(*)() as the erased type, which is always supported.