Il tuo avviso è causato dagli operatori ternari con più tipi nei loro sotto-espressioni, vale a dire: -
cond ? expression of type 1 : expression of type 2
le due espressioni hanno bisogno di valutare allo stesso tipo, che in realtà non vi aiuterà molto .
Per risolvere il tuo problema, posso pensare a due soluzioni, entrambe leggermente negative.
Usa varargs/Funzione Variadica
Definire la funzione utilizzando il '...' parametri e memorizzare i parametri da qualche parte utilizzando i macro dati e definiscono la funzione di destinazione come accettare un va_list. Si perde ogni tipo di sicurezza di tipo, il controllo del compilatore e richiedono metadati extra per le funzioni, oltre a riscrivere la funzione di destinazione per utilizzare una va_list.
goccia di assemblatore e incidere la pila
Te l'avevo detto che era brutto. Data una funzione da chiamare: -
void FuncToCall (type1 arg1, type2 arg2);
creare una funzione: -
void *FuncToCallDelayed (void (*fn) (type1 arg1, type2 arg2), type1 arg1, type2 arg2);
che copia i parametri nello stack ad un blocco allocato dinamicamente di memoria che viene restituita. Poi, quando si desidera chiamare la funzione: -
void CallDelayedFunction (void *params);
con il puntatore la chiamata a FuncToCallDelayed restituito. Ciò quindi spinge i parametri nello stack e chiama la funzione. I parametri e il puntatore della funzione si trovano nel parametro params.
Questo metodo consente di collegarsi a un tipo di processore specifico ma almeno mantiene una qualche forma di controllo dei tipi nell'elenco dei parametri.
Aggiornamento
Ecco una versione del metodo 2, costruita per Visual Studio 2012, IA32, in esecuzione su Win7: -
#include <iostream>
using namespace std;
__declspec (naked) void *CreateDelayedFunction()
{
__asm
{
mov esi,ebp
mov eax,[esi]
sub eax,esi
add eax,4
push eax
call malloc
pop ecx
or eax,eax
jz error
mov edi,eax
sub ecx,4
mov [edi],ecx
add edi,4
add esi,8
rep movsb
error:
ret
}
}
void CallDelayedFunction (void *params)
{
__asm
{
mov esi,params
lodsd
sub esp,eax
mov edi,esp
shr eax,2
mov ecx,eax
lodsd
rep movsd
call eax
mov esi,params
lodsd
add esp,eax
}
}
void __cdecl TestFunction1 (int a, long long b, char *c)
{
cout << "Test Function1: a = " << a << ", b = " << b << ", c = '" << c << "'" << endl;
}
void __cdecl TestFunction2 (char *a, float b)
{
cout << "Test Function2: a = '" << a << "', b = " << b << endl;
}
#pragma optimize ("", off)
void *__cdecl TestFunction1Delayed (void (*fn) (int, long long, char *), int a, long long b, char *c)
{
return CreateDelayedFunction();
}
void *__cdecl TestFunction2Delayed (void (*fn) (char *, float), char *a, float b)
{
return CreateDelayedFunction();
}
#pragma optimize ("", on)
int main()
{
cout << "Calling delayed function1" << endl;
void *params1 = TestFunction1Delayed (TestFunction1, 1, 2, "Hello");
cout << "Calling delayed function2" << endl;
void *params2 = TestFunction2Delayed (TestFunction2, "World", 3.14192654f);
cout << "Delaying a bit..." << endl;
cout << "Doing Function2..." << endl;
CallDelayedFunction (params2);
cout << "Doing Function1..." << endl;
CallDelayedFunction (params1);
cout << "Done" << endl;
}
** Aggiornamento ** Un altro
C'è una terza opzione, come ho menzionato nei commenti, e cioè utilizzare un sistema di messaggistica. Invece di chiamare una funzione, creare un oggetto messaggio del modulo: -
struct MessageObject
{
int message_id;
int message_size;
};
struct Function1Message
{
MessageObject base;
// additional data
};
e quindi avere una ricerca tra i message_id e funzioni reali, con le funzioni e la ricerca definite come: -
void Function1 (Function1Object *message)
{
}
struct Lookup
{
int message_id;
void (*fn) (void *data);
};
Lookup lookups [] = { {Message1ID, (void (*) (void *data)) Function1}, etc };
Come si 'function' dichiarato? Se dipende dagli argomenti, come decidi quale funzione chiamare? – jxh
Sembra che libffi sia * vicino * a quello che vuoi, almeno per la spedizione dinamica. Non aiuta esattamente con la parte di ritardo, ma è probabile che sia specifico per la piattaforma che stai prendendo di mira. Forniscici alcune informazioni sulla tua piattaforma (Linux, Windows, Mac OSX, ecc.) E possiamo aiutarti di più. –
@jxh, 'function' è come printf, può assumere argomenti di diverso tipo. Tutto ciò di cui ho bisogno è di passare alla funzione argomenti correttamente memorizzati (memorizzati in precedenza). – kaspersky