這個問題與Warning (Anachronism): Assigning void(*)(int)
to extern "C" void(*)(int)
有關。在列舉的問題,我們有typedef的聲明爲extern "C"
函數指針:C++是否會從聲明中剝離'extern「C」'?
extern "C" {
typedef void (*SignalHandlerFn) (int);
};
當我們試圖給它分配:
new_handler.sa_handler = (pfn ? reinterpret_cast<SignalHandlerFn>(pfn) :
reinterpret_cast<SignalHandlerFn>(defaultHandler));
這導致錯誤(行號是有點過,但上面的行產生的話):
/opt/solarisstudio12.4/bin/CC -DDEBUG -c test.cpp
...
"ossig.h", line 75: Warning (Anachronism): Using void(*)(int) to initialize extern "C" void(*)(int).
"test.cpp", line 135: Where: While instantiating "SignalHandler<5, 0>::SignalHandler(extern "C" void(*)(int), int)".
"test.cpp", line 135: Where: Instantiated from non-template code.
2 Warning(s) detected.
能告訴我最好的,extern "C"
使用reinterpret_cast
時被丟棄。然而,C演員按預期工作。
我相信Sun Studio 12.4(SunCC 5.13)通過defult使用C++ 03。但是我的問題同時適用於C++ 03和C++ 11,因爲我們現在看到很多都是由於GCC 4.8和4.9的普及。
C++是否會從聲明中剝離extern "C"
?
solaris:~$ cat test.cxx
#include <signal.h>
extern "C" {
typedef void (*SignalHandlerFn) (int);
};
template <int S, bool O=false>
struct SignalHandler
{
SignalHandler(SignalHandlerFn pfn = NULL, int flags = 0) : m_installed(false)
{
struct sigaction new_handler;
do
{
int ret = 0;
ret = sigaction (S, 0, &m_old);
if (ret != 0) break; // Failed
if (m_old.sa_handler != 0 && !O) break;
new_handler.sa_handler = (pfn ? reinterpret_cast<SignalHandlerFn>(pfn) :
reinterpret_cast<SignalHandlerFn>(&SignalHandler::NullHandler));
new_handler.sa_flags = (pfn ? flags : 0);
ret = sigemptyset (&new_handler.sa_mask);
if (ret != 0) break; // Failed
ret = sigaction (S, &new_handler, 0);
if (ret != 0) break; // Failed
m_installed = true;
} while(0);
}
~SignalHandler()
{
if (m_installed)
sigaction (S, &m_old, 0);
}
private:
struct sigaction m_old;
bool m_installed;
static void NullHandler(int /*unused*/) { /* continue*/ }
private:
// Not copyable
SignalHandler(const SignalHandler &);
void operator=(const SignalHandler &);
};
int main(int argc, char* argv[])
{
SignalHandler<SIGTRAP, 0> handler;
return 0;
}
語言鍵是函數的類型的部分(並且可以在其上過載);不幸的是,大多數編譯器都沒有正確實現。 –
謝謝Kerrek。這是否意味着SunCC是正確的,我的SignalHandlerFn錯了,其他編譯器應該拒絕它?或者這是否意味着SunCC錯誤地處理了它?對不起,問。我知道如何解決它;但我仍不清楚問題是什麼。 – jww
你的'NullHandler'肯定是錯誤的,因爲類成員函數從來沒有C鏈接。事實上,GCC和Clang完全忽略了這一點。您可以仔細檢查Embarcadero,我相信這些規則會正確實施這些規則。另一方面,'pfn'應該是正確的。 –