Tworzę rejestrator z następujących sekcjach:stringstream problemem powrót tymczasowy ostream
// #define LOG(x) // for release mode
#define LOG(x) log(x)
log(const string& str);
log(const ostream& str);
na pomysł, aby zrobić:
LOG("Test");
LOG(string("Testing") + " 123");
stringstream s;
LOG(s << "Testing" << 1 << "two" << 3);
To wszystko działa zgodnie z przeznaczeniem, ale kiedy zrobić:
LOG(stringstream() << "Testing" << 1 << "two" << 3);
To nie działa:
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;
}
}
powoduje wyświetlenie "formatu" zawierającego dane śmieci zamiast zwykłego prawidłowego ciągu.
Myślę, że dzieje się tak dlatego, że tymczasowy ostream zwrócony przez operatora < < przeżył ciąg strumienia, z którego pochodzi.
Czy ja się mylę?
(Dlaczego string() działa w ten sposób? Czy dlatego, że zwraca odwołanie do siebie? Zakładam, że tak.)
naprawdę chciałbym zrobić to w ten sposób, jak chciałbym być wyeliminowanie dodatkowy przydział przy logowaniu w trybie zwolnienia.
Wszelkie wskazówki i triki, aby to zrobić w ten sposób, byłyby mile widziane. W moim rzeczywistym rozwiązaniu mam wiele różnych funkcji dziennika i wszystkie są bardziej złożone niż to. Więc wolałbym, aby to zostało jakoś zaimplementowane w kodzie wywołującym. (A nie przez modyfikację mojego #define jeśli to możliwe)
Wystarczy dać wyobrażenie, przykład jednego z moich rzeczywistych #defines:
#define LOG_DEBUG_MSG(format, ...) \
LogMessage(DEBUG_TYPE, const char* filepos, sizeof(__QUOTE__(@__VA_ARGS__)), \
format, __VA_ARGS__)
który pasuje varargs printf-podobne funkcje dziennika biorąc char *, Funkcje string() i ostream() oraz funkcje inne niż vararg przy użyciu string(), exception() i HRESULT.
Co masz na myśli, mówiąc "to nie działa"? –
Masz rację, powinieneś wziąć kopię ciągu, więc 'format' powinien być typu' std :: string', a nie typu 'const std :: string &'. Możesz jednak po prostu wstawić 'dynamic_cast' do wyrażenia' cout' i całkowicie stracić zmienną. – KayEss
Nie, nie muszę robić kopii. Zawartość ciągu zwracanego przez str() ma gwarantowaną stałą wartość (podobnie jak string :: c_str()) pomiędzy kolejnymi wywołaniami tych metod. Jeśli chodzi o to, dlaczego robię to w ten sposób, potrzebuję ciąg formatu, ponieważ faktycznie chcę go przekazać albo do funkcji pojedynczego parametru, biorąc ciąg znaków, albo do metody VARARGS przyjmującej znak * w zależności od tego, jakie inne parametry są odbierane. (Ale to wszystko wykracza poza zakres mojego pytania - na co odpowiedziano zadowalająco). – Marius