Ясно, что приведение между указателями на функции и указателями на объекты является неопределенным поведением в общем смысле, но POSIX (см .: dlsym) и WinAPI (см .: GetProcAddress) требуют этого.
Учитывая это, и учитывая тот факт, что такой код в любом случае нацелен на специфичный для платформы API, его переносимость на платформы, где указатели функций и указатели объектов несовместимы, на самом деле не имеет значения.
Но -Wpedantic предупреждает об этом в любом случае, и #pragma GCC diagnostic ignored "-Wpedantic"
не имеет никакого эффекта:
warning: ISO C++ forbids casting between pointer-to-function and pointer-to-object [enabled by default]
Я хочу сохранить -Wpedantic включен, так как он дает хорошие предупреждения, но я не хочу, чтобы настоящие предупреждения и ошибки терялись в море несущественных предупреждений о указателе функции на приведение указателя объекта.
Есть ли способ сделать это?
Запуск GCC 4.8.0 в Windows (MinGW):
gcc (rubenvb-4.8.0) 4.8.0
ОБРАЗЕЦ КОДА
#include <windows.h>
#include <iostream>int main (void) {
std::cout << *reinterpret_cast<int *>(GetProcAddress(LoadLibraryA("test.dll"),"five")) << std::endl;
}
Излучает (с -Wpedantic):
warning_demo.cpp: In function 'int main()':
warning_demo.cpp:7:87: warning: ISO C++ forbids casting between pointer-to-funct
ion and pointer-to-object [enabled by default]
std::cout << *reinterpret_cast<int *>(GetProcAddress(LoadLibraryA("test.dll"),
"five")) << std::endl;
^
Я думаю, что вы могли бы использовать g ++ system_header
директива здесь:
wrap_GetProcAddress.h:
#ifndef wrap_GetProcAddress_included
#define wrap_GetProcAddress_included
#pragma GCC system_header
template <typename Result>
Result GetProcAddressAs( [normal parameters] )
{
return reinterpret_cast<Result>(GetProcAddressAs( [normal parameters] ));
}
#endif
Это отлично работает.
template <typename RESULT, typename ...ARGS>
void * make_void_ptr(RESULT (*p)(ARGS...)) {
static_assert(sizeof(void *) == sizeof(void (*)(void)),
"object pointer and function pointer sizes must equal");
void *q = &p;
return *static_cast<void **>(q);
}
Всегда есть трюк с memcpy, который вы можете использовать:
int (*f)() = 0;
int *o;
memcpy(&o, &f, sizeof(int*));
Вы можете увидеть это на ideone: m
генерирует предупреждения, в то время как g
в порядке.
Что касается других действий, которые вы, возможно, захотите предпринять: одной очевидной возможностью будет «исправить» заголовок, определяющий dlsym
на самом деле вернуть указатель на функцию (например, void (*)()
). Удачи с этим.