以下代码可在GCC上正常编译,但在Clang上会出错:

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

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

我尝试了以下解决方案,除了C风格的转换外,它们都出错:

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

错误:
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: reinterpret_cast from 'const MyFuncPtr *' (aka 'void (const *)()') to 'MyFuncPtr *' (aka 'void (*)()') casts away
  qualifiers

C样式转换:
MyFuncPtr* myTestPtr = (MyFuncPtr*) ptr;

成功!

问题:
为什么const_cast在函数指针上不起作用?
使用C样式的强制转换是唯一的解决方案吗?
为什么在没有强制转换的情况下在GCC上可以正常工作?

提前致谢!

编译器版本:
* G++版本4.6.3
* clang版本3.5.0.210790

最佳答案

在您的代码中,MyFuncPtr是一种函数类型(不是函数指针类型)。您的代码尝试使用const MyFuncPtr类型,该类型将const应用于函数类型。

但是,根据C++ 14 [dcl.fct] / 6中的注释,没有像const限定的函数类型这样的东西:



本节主要讨论cv-qualifier-seq,这是在成员函数之后出现的限定符。但是,顺便说一句,似乎可以指定通常忽略应用于函数类型的cv限定词。

因此,您的代码应与以下代码相同:

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

这意味着clang错误地报告了错误。

07-24 09:46
查看更多