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

Time:10-10

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.

CodePudding user response:

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.

CodePudding user response:

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

Basically, there is no guarantee for a full-round trip between void* and a function pointer.

This can be seen from expr.reinterpret.cast#8 which says:

Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning of such a conversion is implementation-defined, except that if an implementation supports conversions in both directions, converting a prvalue of one type to the other type and back, possibly with different cv-qualification, shall yield the original pointer value.

  • Related