Sto tentando di includere le funzioni API di Windows per controllare gli errori quando lo scelgo. Come ho scoperto in una precedente domanda SO, potrei utilizzare una funzione modello per chiamare la funzione API e quindi chiamare GetLastError()
per recuperare qualsiasi errore che potrebbe essere impostato. Potrei quindi passare questo errore alla mia classe Error
per farmelo sapere.Verifica in fase di compilazione se Argomento modello non è valido
Ecco il codice per la funzione template:
template<typename TRet, typename... TArgs>
TRet Wrap(TRet(WINAPI *api)(TArgs...), TArgs... args)
{
TRet ret = api(args...);
//check for errors
return ret;
}
Usando questo posso avere codice come segue
int WINAPI someFunc (int param1, BOOL param2); //body not accessible
int main()
{
int ret = someFunc (5, true); //works normally
int ret2 = Wrap (someFunc, 5, true); //same as above, but I'll get a message if there's an error
}
Questo funziona meravigliosamente. Tuttavia, c'è un possibile problema. Prendere la funzione
void WINAPI someFunc();
Quando subbing questo nella funzione del modello, appare come segue:
void Wrap(void(WINAPI *api)())
{
void ret = api(); //<-- ahem! Can't declare a variable of type void...
//check for errors
return ret; //<-- Can't return a value for void either
}
Per aggirare il problema, ho cercato di creare una versione del modello in cui ho sostituito TRet
con void
. Sfortunatamente, questo in realtà causa solo un'ambiguità di cui uno da usare.
A parte questo, ho provato ad utilizzare
if (strcmp (typeid (TRet).name(), "v") != 0) //typeid(void).name() == "v"
{
//do stuff with variable to return
}
else
{
//do stuff without returning anything
}
Tuttavia, typeid
è un confronto di esecuzione, in modo che il codice ancora non compilare dovuta al tentativo di dichiarare una variabile vuoto, anche se non lo sarà mai.
Successivamente, ho provato a utilizzare std::is_same <TRet, void>::value
anziché typeid
, ma ho scoperto che si trattava anche di un confronto di runtime.
A questo punto, non so cosa provare dopo. C'è qualche possibilità di far credere al compilatore che so che cosa sto facendo funzionerà? Non mi interessa allegare un argomento in più al numero Wrap
, ma non sono riuscito a ottenere nulla da questo.
Uso Code :: Blocks con GNU G ++ 4.6.1 e Windows XP, oltre a Windows 7. Grazie per qualsiasi aiuto, anche se mi sta dicendo che dovrò finire semplicemente non usando Wrap
per le funzioni che restituiscono nulla.
Comprendo perché la specializzazione del tipo restituito come void non ha funzionato (non si può disambiguare sui tipi restituiti) ma la specializzazione con void ** e ** l'aggiunta di un parametro aggiuntivo dovrebbe funzionare, cosa è successo? Potrebbe essere necessario invocare con tipi espliciti. – Tod
Interessante domanda. Nota a margine: oltre a non essere controllata staticamente, anche la soluzione 'typeid' non è portabile. Lo standard non garantisce la stringa restituita da 'type_info :: name()'. – Thomas
Non ho pensato di combinare i due. Ci proverò. Grazie anche per l'heads-up sul problema dei typeid. – chris