This is a tangential follow up to my previous question The address of a function matching a bool vs const void* overload. The answerer explained:
The [C++11] standard does not define any standard conversions from a "pointer to function" to a "pointer to
void."It's hard to provide a quote for the absence of something, but the closest I can do is C++11 4.10/2 [conv.ptr]:
A prvalue of type “pointer to cv
T,” whereTis an object type, can be converted to a prvalue of type “pointer to cvvoid”. The result of converting a “pointer to cvT” to a “pointer to cvvoid” points to the start of the storage location where the object of typeTresides, as if the object is a most derived object (1.8) of type T (that is, not a base class subobject). The null pointer value is converted to the null pointer value of the destination type.(emphasis mine)
Assuming func is declared void func();, if you do a C-style cast, i.e. (void*) func, the cast will be successful. static_cast<void*>(func) however is invalid, but reinterpret_cast<void*>(func) will be successful. What you cannot do however is convert the subsequently converted pointer back to its original type. For example,
Fine:
int main() {
  int* i;
  void* s = static_cast<void*>(i);
  i = static_cast<int*>(s);
  s = reinterpret_cast<void*>(i);
  i = reinterpret_cast<int*>(s);
}
Not fine:
void func() { }
int main() {
  void* s = reinterpret_cast<void*>(func);
  reinterpret_cast<decltype(func)>(s);
}
N3337 starts off by saying,
[expr.reinterpret.cast]
The result of the expression
reinterpret_cast<T>(v)is the result of converting the expressionvto typeT. IfTis an lvalue reference type or an rvalue reference to function type, the result is an lvalue; ifTis an rvalue reference to object type, the result is an xvalue; otherwise, the result is a prvalue and the lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are performed on the expression v. Conversions that can be performed explicitly usingreinterpret_castare listed below. No other conversion can be performed explicitly usingreinterpret_cast.
I bolded the language that I believe is key here. The last part seems to imply that if the conversion is not listed, it's illegal. In brief summary, the allowed conversions are:
- A pointer can be explicitly converted to any integral type large enough to hold it.
- A value of integral type or enumeration type can be explicitly converted to a pointer.
- A function pointer can be explicitly converted to a function pointer of a different type.
- An object pointer can be explicitly converted to an object pointer of a different type.
- Converting a function pointer to an object pointer type or vice versa is conditionally-supported.
- The null pointer value (4.10) is converted to the null pointer value of the destination type.
- A prvalue of type "pointer to member of Xof typeT1" can be explicitly converted to a prvalue of a different type "pointer to member of Y of typeT2" ifT1andT2 are both function types or both object types.
- An lvalue expression of type T1can be cast to the type "reference toT2" if an expression of type "pointer toT1" can be explicitly converted to the type "pointer toT2" using a reinterpret_cast.
void* is not a function pointer and objects don't have function or void type.
[basic.types]
An object type is a (possibly cv-qualified) type that is not a function type, not a reference type, and not a void type.
So maybe I'm grasping at straws, but it seems reinterpret_cast<void*>(func) is illegal. However, on the other hand, [expr.static.cast]/5 says "Otherwise, the static_cast shall perform one of the conversions listed below. No other conversion shall be
performed explicitly using a static_cast." the key difference being "shall" and "can". Is this enough to make the reinterpret_cast legal or am I missing something else?
 
    