GCC предупреждает о указателе функции на указатель объекта

Четкое литье между указателями функций и указателями объектов - это поведение undefined в общем смысле, но 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;

       ^

Ответ 1

Я думаю, вы могли бы использовать директиву 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

Ответ 2

Это отлично работает.

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);
}

Ответ 3

Всегда есть трюк memcpy, который вы можете использовать:

int (*f)() = 0;
int *o;
memcpy(&o, &f, sizeof(int*));

Вы можете увидеть его на ideone: m генерирует предупреждения, а g - в порядке.

Что касается других действий, которые вы можете предпринять: одной очевидной возможностью было бы "исправить" заголовок, определяющий dlsym, чтобы фактически вернуть указатель на функцию (например, void (*)()). Удачи вам в этом.