Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cast away constness on a function pointer?

Tags:

c++

casting

clang

The following code compiles clean on GCC but gets an error on Clang:

typedef void (MyFuncPtr)();
void foo(const MyFuncPtr* ptr)
{   
    MyFuncPtr* myTestPtr = ptr;
}

Clang error:

error: cannot initialize a variable of type 'MyFuncPtr *' (aka 'void (*)()') with an lvalue of type 'const MyFuncPtr *'
  (aka 'void (const *)()')

I have tried the following solutions and they all get errors except for the C-style cast:

const_cast:

MyFuncPtr* myTestPtr = const_cast<MyFuncPtr*>(ptr);

Error:

error: const_cast to 'MyFuncPtr *' (aka 'void (*)()'), which is not a reference, pointer-to-object, or pointer-to-data-member

reintepret_cast:

MyFuncPtr* myTestPtr = reinterpret_cast<MyFuncPtr*>(ptr);

Error:

error: reinterpret_cast from 'const MyFuncPtr *' (aka 'void (const *)()') to 'MyFuncPtr *' (aka 'void (*)()') casts away
  qualifiers

C-style cast:

MyFuncPtr* myTestPtr = (MyFuncPtr*) ptr;

Success!

Questions:
Why doesn't const_cast work on function pointers?
Is using a C-style cast the only solution?
Why does this work on GCC with no casting?

Thanks in advance!

COMPILER VERSIONS:
*G++ version 4.6.3
*clang version 3.5.0.210790

like image 213
Chadness3 Avatar asked Aug 14 '26 17:08

Chadness3


1 Answers

In your code, MyFuncPtr is a function type (not a function pointer type). Your code tries to use the type const MyFuncPtr, which is applying const to a function type.

However, according to the note in C++14 [dcl.fct]/6, there is no such thing as a const-qualified function type:

The effect of a cv-qualifier-seq in a function declarator is not the same as adding cv-qualification on top of the function type. In the latter case, the cv-qualifiers are ignored. [Note: a function type that has a cv-qualifier-seq is not a cv-qualified type; there are no cv-qualified function types. —end note ]

This section is primarily talking about cv-qualifier-seq, which is the qualifiers that occur after a member function. However, in passing, it seems to specify that cv-qualifiers applied to a function type in general are ignored.

So your code ought to be the same as:

typedef void (MyFuncPtr)();
void foo(MyFuncPtr* ptr)
{   
    MyFuncPtr* myTestPtr = ptr;
}

which would mean clang is bugged to report an error.

like image 147
M.M Avatar answered Aug 17 '26 06:08

M.M



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!