Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting a function pointer into a noexcept specified function pointer

Say I have these declarations:

using fp_type = void(*)();
using fp2_type = void(*)() noexcept;

and

void func(){}
fp_type fp(func);

Is the cast fp2_type(fp) well-formed? The other way around (casting a noexcept-specified function pointer into a function pointer without a noexcept specifier)?

like image 247
user1095108 Avatar asked Feb 22 '16 10:02

user1095108


1 Answers

This is ill-formed in C++14 and earlier:

using fp2_type = void(*)() noexcept;

due to N4140 [except.spec]/2:

An exception-specification shall not appear in a typedef declaration or alias-declaration.

So I'm going to assume that the question is for C++1z, where exception specification is part of the type system.


[conv.fctptr]/1:

A prvalue of type “pointer to noexcept function” can be converted to a prvalue of type “pointer to function”. The result is a pointer to the function.

Thus, void (*)() noexcept can be (implicitly) converted to void (*)().

[expr.static.cast]/7:

The inverse of any standard conversion sequence (Clause [conv]) not containing a [(various other cases omitted)] function pointer ([conv.fctptr]) conversion, can be performed explicitly using static_cast.

Nothing else in [expr.static.cast] allows converting void (*)() to void (*)() noexcept either, so this is not a conversion that can be performed by a static_cast.

[expr.reinterpret.cast]/6:

A function pointer can be explicitly converted to a function pointer of a different type. The effect of calling a function through a pointer to a function type ([dcl.fct]) that is not the same as the type used in the definition of the function is undefined. Except that converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are function types) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified. [ Note: see also [conv.ptr] for more details of pointer conversions. — end note ]

So reinterpret_cast can perform this conversion.

Since fp2_type(fp) is equivalent to the C-style cast (fp2_type) fp ([expr.type.conv]/1), and since C-style casts do a reinterpret_cast when static_cast is not possible (ignoring const_cast for simplicity, as it's not relevant here), fp2_type(fp) is a well-formed reinterpret_cast. The result of such a cast cannot be used except to cast it back, however.

like image 96
T.C. Avatar answered Nov 17 '22 11:11

T.C.