Предупреждение (анахронизм): назначение void (*) (int) внешнему & quot; C & quot; аннулированию (*) (целое)

У меня проблемы с компилятором Sun C ++. Я читал Оракула Работа с указателями на функции [из C ++]. Это хорошее чтение, и у меня сложилось впечатление, что SunCC является наиболее совместимым среди всех компиляторов в этой области (хотя это вызывает у меня проблемы).

Тестовый код ниже, а строка 24 new_handler.sa_handler = (pfn ? pfn : &SignalHandler::NullHandler);, Развертывание троичного оператора показывает, что это проблема: new_handler.sa_handler = pfn;,

SunCC 5.11

$ /opt/solstudio12.2/bin/CC test.cxx
"test.cxx", line 24: Warning (Anachronism): Assigning void(*)(int) to extern "C" void(*)(int).
"test.cxx", line 58:     Where: While instantiating "SignalHandler<5, 0>::SignalHandler(void(*)(int), int)".
"test.cxx", line 58:     Where: Instantiated from non-template code.

SunCC 5.12

$ /opt/solarisstudio12.3/bin/CC test.cxx
"test.cxx", line 24: Warning (Anachronism): Assigning void(*)(int) to extern "C" void(*)(int).
"test.cxx", line 58:     Where: While instantiating "SignalHandler<5, 0>::SignalHandler(void(*)(int), int)".
"test.cxx", line 58:     Where: Instantiated from non-template code.

SunCC 5.13

$ /opt/solarisstudio12.4/bin/CC test.cxx
"test.cxx", line 24: Warning (Anachronism): Using void(*)(int) to initialize extern "C" void(*)(int).
"test.cxx", line 58:     Where: While instantiating "SignalHandler<5, 0>::SignalHandler(void(*)(int), int)".
"test.cxx", line 58:     Where: Instantiated from non-template code.

SunCC 5.14

$ /opt/developerstudio12.5/bin/CC test.cxx
$

Мне не совсем понятно, в чем проблема. Вот аналогичная проблема на платах Oracle, но OP в основном сообщается RTFM: Sun Studio 11 «Предупреждение (анахронизм)».

Как мне разрешить анахроническое предупреждение?


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 ? pfn : &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;
}

2

Решение

Вы можете изменить SignalHandler :: NullHandler на обычную функцию C (назовем ее SignalHandler_NullHandler).
Затем оберните оба SignalHandler_NullHandler и SignalHandlerFn во внешнюю «C».

КСТАТИ. Я догадывался, как «выровнять» эти две функции, но вы лучше объяснили в своем комментарии, что существует проблема с приведением C / C ++.

2

Другие решения

В выражении:

pfn ? pfn : &SignalHandler::NullHandler

второй и третий операнды имеют разные типы (так как один указывает на функцию с языковой связью «C», а другой указывает на функцию с языковой связью «C ++»); и не существует неявного преобразования, которое изменяет языковые связи.

Так что это выражение плохо сформировано. Другой ответ предполагает использование приведений, однако это может подавить диагностику за счет молчаливого неопределенного поведения во время выполнения: вызова функции через указатель на функцию другого типа.

Возможно, что определенные компиляторы предоставляют расширения для определения поведения в любом сценарии, который, конечно, не определен стандартом C ++. (Или все равно «работать в любом случае»).

Моя рекомендация будет заменить SignalHandler::NullHandler с функцией, которая имеет связь языка Си. Это не может быть членом класса, потому что грамматика языка исключает extern "C" от появления внутри определения класса.

1

По вопросам рекламы [email protected]