Безопасно ли выпустить void (* p) (SomeType *) на void (* p) (void *)

Предположим, что у меня есть функция, как показано ниже:

void fun(void* p){
    SomeType* p = reinterpret_cast<SomeType*>(p);
    ...
}

Подпись требуется для api. Я просто задаюсь вопросом, могу ли я просто написать его как.

void fun(SomeType* p){
    ...
}

И добавьте его в void (*)(void*).

Ответ 1

Пока вы можете указывать указатели функций на другие указатели на функции и обратно, вызов функции с помощью указателя, который не соответствует его сигнатуре, - это поведение undefined. Вы не можете просто передать его и перейти к API.

В C и С++ 03 вам нужно создать именованную функцию-обертку, которая соответствует сигнатуре и преформирует трансляцию. В С++ 11 и более поздних версиях вместо этого вы можете просто использовать вместо лямбда без захвата (правильно отбросить):

void fun(SomeType* p){
    ...
}

int main() {
  api_call(+[](void *v) {
    fun(static_cast<SomeType*>(v));
  });
}

+ перед лямбдой заставляет его преобразовываться в обычный указатель функции, пока он не захватывает. Это не строго необходимо, но делает намерение более явным ИМО без лишних слов.