Sto creando un registratore con le seguenti sezioni:stringstream problema ritorno ostream temporanea
// #define LOG(x) // for release mode
#define LOG(x) log(x)
log(const string& str);
log(const ostream& str);
Con l'idea di fare:
LOG("Test");
LOG(string("Testing") + " 123");
stringstream s;
LOG(s << "Testing" << 1 << "two" << 3);
Tutto questo funziona come previsto, ma quando lo faccio:
LOG(stringstream() << "Testing" << 1 << "two" << 3);
non funziona:
void log(const ostream& os)
{
std::streambuf* buf = os.rdbuf();
if(buf && typeid(*buf) == typeid(std::stringbuf))
{
const std::string& format = dynamic_cast<std::stringbuf&>(*buf).str();
cout << format << endl;
}
}
risultati in "formato" contenente dati indesiderati anziché la solita stringa corretta.
Penso che ciò sia dovuto al fatto che l'ostream temporaneo restituito dall'operatore < < sopravvive allo stringstream da cui proviene.
Oppure ho sbagliato?
(Perché la stringa() opera in questo modo? E 'perché restituisce un riferimento a se stesso? Sto assumendo di sì.)
Mi piacerebbe davvero farlo in questo modo, come vorrei essere eliminando il un'allocazione aggiuntiva quando si accede alla modalità di rilascio.
Qualsiasi suggerimento o trucchetto per farlo in questo modo sarebbe ben accetto. Nella mia attuale soluzione ho molte funzioni di registro diverse e sono tutte più complesse di così. Quindi preferirei che fosse implementato in qualche modo nel codice chiamante. (E non modificando il mio # define se possibile)
Tanto per dare un'idea, un esempio di uno dei miei # definisce effettivi:
#define LOG_DEBUG_MSG(format, ...) \
LogMessage(DEBUG_TYPE, const char* filepos, sizeof(__QUOTE__(@__VA_ARGS__)), \
format, __VA_ARGS__)
che corrisponde varargs funzioni di log-printf come prendere char *, string() e ostream() così come le funzioni non vararg assumono string(), exception() e HRESULT.
Cosa intendi per "non funziona"? –
Hai ragione, dovresti prendere una copia della stringa, quindi 'format' dovrebbe essere di tipo' std :: string' non di tipo 'const std :: string &'. Puoi comunque mettere il 'dynamic_cast' nell'espressione' cout' e perdere la variabile del tutto. – KayEss
No, non ho bisogno di fare una copia. Il contenuto della stringa restituita da str() è garantito per rimanere costante (nello stesso modo in cui string :: c_str()) tra le chiamate successive a questi metodi. Per quanto riguarda il motivo per cui lo sto facendo, ho bisogno della stringa di formato poiché in realtà voglio passare a una funzione a parametro singolo prendendo una stringa, oa un metodo VARARGS che prende un carattere * a seconda di quali altri parametri sono stati ricevuti. (Ma tutto questo è al di fuori della portata della mia domanda - a cui è stata data una risposta soddisfacente) – Marius