Ok, risolto: in gcc __FUNCSIG__ va rimpiazzato con __PRETTY_FUNCTION__.
Ok, risolto: in gcc __FUNCSIG__ va rimpiazzato con __PRETTY_FUNCTION__.
"Let him who has understanding reckon the number of the beast, for it is a human number.
Its number is rw-rw-rw-."
Giusto, __FUNCSIG__ è specifico di VC++; purtroppo non mi pare ci sia nulla di standard per avere il nome della funzione corrente in formato leggibile.
Amaro C++, il gusto pieno dell'undefined behavior.
Beh in gcc ho trovato l'equivalente.
Adesso sto cercando di capire lo strano comportamento di __PRETTY_FUNCTION__:
funziona SOLO se è definito da solo. Intendo che
Se insieme a __PRETTY_FUNCTION__ inserisco QUALSIASI altra cosa, non lo compila dando gli errori di parsing che dicevo sopra.codice:#define ERROR_STD_PROLOG "Oh noes! " __FILE__ ":" TOSTRING( __LINE__ ) //compila #define ERROR_STD_PROLOG __PRETTY_FUNCTION__ //compila #define ERROR_STD_PROLOG "Errore in: "__PRETTY_FUNCTION__ //non compila #define ERROR_STD_PROLOG __PRETTY_FUNCTION__ __FILE__ ":" TOSTRING( __LINE__ ) //non compila![]()
"Let him who has understanding reckon the number of the beast, for it is a human number.
Its number is rw-rw-rw-."
Dimenticavo: ho guardato l'output del preprocessore, e ho scoperto che
1) è gigantesco OO
2) se __PRETTY_FUNCTION__ è lasciato da solo viene espanso. Se inserisco qualsiasi altra cosa su quella linea, le altre macro (come __FILE__) vengono espanse, ma __PRETTY_FUNCTION__ no.
"Let him who has understanding reckon the number of the beast, for it is a human number.
Its number is rw-rw-rw-."
Da quanto leggo qui __PRETTY_FUNCTION__ non viene effettivamente considerato come una macro del preprocessore, ma come una variabile.![]()
Amaro C++, il gusto pieno dell'undefined behavior.
Bene, non so se a qualcuno serva, ma direi che il problema è risolto.
Allora:
__PRETTY_FUNCTION__ è una const char []
__FILE__ è una const char []
__LINE__ è un int
Per cui, se a qualcuno dovesse servire, ecco qui una piccola classe che crea una stringa d'errore (scommetto che entro 5 minuti da quando la posto MItaly mi posterà 20 buoni motivi per cui non usarla)
error_maker.hpp
error:_maker.cccodice:#include <string> using namespace std; /* Abstract class that generates complete error messages. The message generated is a string containing the function name the filename the line error a custom message */ class error_maker { public: static string create_error_string( const string& function, const string& filename, const int line, const string& message); private: virtual void dummy(void) = 0; //makes the class abstract };
Esempio:codice:#include <sstream> #include <string> #include "error_maker.hpp" using namespace std; string error_maker::create_error_string( const string& function, const string& filename, const int line, const string& message) { stringstream ss(stringstream::in | stringstream::out); string result; ss << "Error raised." << endl; ss << "\tIn function: " << function << endl; ss << "\tIn file: " << filename << ":" << line << endl; ss << "\tMessage: " << message << endl; return ss.str(); }
codice:if (row >= _dim || column >= _dim) throw out_of_bounds_exception( error_maker::create_error_string( __PRETTY_FUNCTION__, __FILE__, __LINE__, ""));
"Let him who has understanding reckon the number of the beast, for it is a human number.
Its number is rw-rw-rw-."
Be', è più o meno quello che avevo fatto io una volta, con la differenza che nel mio caso memorizzavo anche il valore di GetLastError (ero su Windows, su *NIX si memorizzerebbe errno) dato che spesso veniva comodo.
Qualche suggerimento: puoi fare una macro (nel mio caso l'avevo chiamata EXC, EXception Context) in modo da evitare di dover scrivere tutte le volte __PRETTY_FUNCTION__ e compagnia:
per cui diventa:codice:#define EXC __PRETTY_FUNCTION__, __FILE__, __LINE__
Volendo potresti anche fare sì che sia la classe eccezione ad accettare direttamente i parametri in questione, magari adottando la convenzione di tenerli per ultimi:codice:if (row >= _dim || column >= _dim) throw out_of_bounds_exception( error_maker::create_error_string( EXC, "Messaggio"));
Per inciso, la out_of_bounds_exception forse potresti farla derivare da std:codice:if (row >= _dim || column >= _dim) throw out_of_bounds_exception("Il numero di righe eccetera eccetera", EXC);ut_of_range.
Amaro C++, il gusto pieno dell'undefined behavior.
Anche meglio, l'ho sostituita con quella (e adesso ne sostituirò anche un altra con invalid_argument).
Tra l'altro il bello è che adesso il mio programma ha dei modi fighissimi di segnalarmi l'errore, ma non ho ancora risolto il problema che causa l'eccezione che sto così argutamente sollevando![]()
"Let him who has understanding reckon the number of the beast, for it is a human number.
Its number is rw-rw-rw-."
Originariamente inviato da Ippo343
Anche meglio, l'ho sostituita con quella (e adesso ne sostituirò anche un altra con invalid_argument).
Tra l'altro il bello è che adesso il mio programma ha dei modi fighissimi di segnalarmi l'errore, ma non ho ancora risolto il problema che causa l'eccezione che sto così argutamente sollevando![]()
tipico.
Amaro C++, il gusto pieno dell'undefined behavior.
non hai colto che la:Originariamente inviato da Ippo343
Più che altro è che più in giù nel metodo c'è una chiamata che può generare la stessa eccezione, e non ho pensato a intercettare anche quella.
L'idea di loggare file e linea mi sembra ottima, ma una volta risolto il problema vorrei di nuovo tornare alle eccezioni: questo perchè in sostanza quella funzione permette all'user di eliminare una riga e una colonna dalla matrice, ma come ben sai, tutto l'input è malvagio
Cioè, se l'utente inserisce riga e colonna sbagliati, viene sollevata un'eccezione, gli do del cretino, e può riprovare... Se il programma termina loggando l'errore bisogna riavviarlo da capo![]()
può essere facilmente espansa in modo che (templatizzandola) YourRuntimeAssertFunction lanci l'eccezione che desideri.. (oltre a loggare esattamente l'espressione che fa fallire l'asserzione mediante # come ti ha gia' mostrato MItaly)codice:#define RuntimeAssert(theAssertion) YourRuntimeAssertFunction((theAssertion), __FILE__, __LINE__)
Analogamente puoi definire una LogicAssert che (solitamente) viene valutata solo nella DEBUG.
;-)