(erledigt) [C++] stringstream::flush() überladen
- Krishty
- Establishment
- Beiträge: 8305
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
(erledigt) [C++] stringstream::flush() überladen
Hi,
Ich möchte einen eigenen String-Stream entsprechend ::std::wstringstream, der sich von diesem nur in der Funktion flush() unterscheidet.
Einfach abzuleiten ist aber nicht möglich, weil viele Spezialisierungen des Operators << globale Funktionen sind. Die Überladene Funktion wird also nie erreicht, das ist allgemein bekannt.
Als Lösung wird oft eine Containerklasse vorgeschlagen, die den operator << als Template anbietet und an den enthaltenen ::std::wstringstream weiterleitet. In meinem Fall hilft mir das aber nicht, denn flush() lässt sich damit immernoch nicht überladen.
Wie bekomme ich nun einen Stream mit voller Kompatibilität zu ::std::wstringstream, aber mit überladenem flush() hin?
Gruß, Ky
Ich möchte einen eigenen String-Stream entsprechend ::std::wstringstream, der sich von diesem nur in der Funktion flush() unterscheidet.
Einfach abzuleiten ist aber nicht möglich, weil viele Spezialisierungen des Operators << globale Funktionen sind. Die Überladene Funktion wird also nie erreicht, das ist allgemein bekannt.
Als Lösung wird oft eine Containerklasse vorgeschlagen, die den operator << als Template anbietet und an den enthaltenen ::std::wstringstream weiterleitet. In meinem Fall hilft mir das aber nicht, denn flush() lässt sich damit immernoch nicht überladen.
Wie bekomme ich nun einen Stream mit voller Kompatibilität zu ::std::wstringstream, aber mit überladenem flush() hin?
Gruß, Ky
Zuletzt geändert von Krishty am 22.07.2009, 23:22, insgesamt 1-mal geändert.
Re: [C++] stringstream::flush() überladen
Hi,
Ich wollte grad antworten: "Leite doch von std::basic_stringbuf ab und setze diesen anstatt den standard std::basic_stringbuf auf deinen Stream." Doch dann musste ich feststellen, dass std::basic_stringstream nur die "Get-Version" von rdbuf() bereitstellt :( Warum das so ist, ist mir schleierhaft...
Ansonsten fällt mir grad auch nicht ein, wie man flush() für einen stringstream bereitstellen könnte. Aber Wenn ich mal fragen darf, warum braucht dein stringstream denn ein flush()? Das ergibt auf den ersten Blick nämlich gar keinen Sinn ;-)
Da verstehst du glaub ich was falsch. Die Operatoren << und >> arbeiten auf der Basis von std::basic_ostream bzw. std::basic_istream und nicht für std::basic_stringstream. Und da ist glaube ich auch dein Problem: da flush() nicht virtual ist, wird es in deiner abgeleiteten Klasse durch die Basisklassenreferenzen nicht aufgerufen. Ein manuelles .flush() auf deinem abgeleiteten Stream wird zwar funktionieren, aber auch der Manipulator std::flush wird den Dienst verweigern, da std::flush auch std::basic_ostream::flush() aufruft und nicht deinen.Krishty hat geschrieben:Einfach abzuleiten ist aber nicht möglich, weil viele Spezialisierungen des Operators << globale Funktionen sind. Die Überladene Funktion wird also nie erreicht, das ist allgemein bekannt.
Ich wollte grad antworten: "Leite doch von std::basic_stringbuf ab und setze diesen anstatt den standard std::basic_stringbuf auf deinen Stream." Doch dann musste ich feststellen, dass std::basic_stringstream nur die "Get-Version" von rdbuf() bereitstellt :( Warum das so ist, ist mir schleierhaft...
Ansonsten fällt mir grad auch nicht ein, wie man flush() für einen stringstream bereitstellen könnte. Aber Wenn ich mal fragen darf, warum braucht dein stringstream denn ein flush()? Das ergibt auf den ersten Blick nämlich gar keinen Sinn ;-)
- Krishty
- Establishment
- Beiträge: 8305
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] stringstream::flush() überladen
Stimmt natürlich!Biolunar hat geschrieben:Die Operatoren << und >> arbeiten auf der Basis von std::basic_ostream bzw. std::basic_istream und nicht für std::basic_stringstream. […] da flush() nicht virtual ist, wird es in deiner abgeleiteten Klasse durch die Basisklassenreferenzen nicht aufgerufen.
Das ist das Problem, die vielen Stream-Objekte sind für jemanden, der da nicht drinsteckt, sehr schwer zu verstehen (und für den Rest scheinbar auch nicht ganz transparent) … ich habe schon die C++-Referenzen abgeklappert, aber das ist einfach zuviel Information um sofort durchzublicken.Biolunar hat geschrieben:Ich wollte grad antworten: "Leite doch von std::basic_stringbuf ab und setze diesen anstatt den standard std::basic_stringbuf auf deinen Stream." Doch dann musste ich feststellen, dass std::basic_stringstream nur die "Get-Version" von rdbuf() bereitstellt :( Warum das so ist, ist mir schleierhaft...
Ich dachte mir, ich könnte einen stringstream mit Debug-Output füllen und den dann zeilenweise auf den Bildschirm flushen … so etwas wie ::std::cout … Momentan fülle ich überall ::std::wstringstreams und rufe dann meine Output-Funktion mit deren .str()-Objekten auf … ich lasse mich da aber gern besserer Wege belehren :DBiolunar hat geschrieben:Aber Wenn ich mal fragen darf, warum braucht dein stringstream denn ein flush()? Das ergibt auf den ersten Blick nämlich gar keinen Sinn ;-)
Re: [C++] stringstream::flush() überladen
Also quasi anstatt sowas: logger_object.write(text.str()); sowas wie text.flush();? Die Idee da hinter fände ich nicht schlecht, da das flush() standardmäßig sowieso nix macht, allerdings wird damit der Sinn von flush() verändert. Dieses wiederrum halte ich für eine schlechte Idee. Wie wäre es, wenn du std::clog oder std::wclog für deine Ausgaben ummünzt? Dann hättest du immer ein clog << text.str();.
- Krishty
- Establishment
- Beiträge: 8305
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] stringstream::flush() überladen
Neinein – bisher mache ich es so:Biolunar hat geschrieben:Also quasi anstatt sowas: logger_object.write(text.str()); sowas wie text.flush();? Die Idee da hinter fände ich nicht schlecht, da das flush() standardmäßig sowieso nix macht, allerdings wird damit der Sinn von flush() verändert. Dieses wiederrum halte ich für eine schlechte Idee.
Code: Alles auswählen
::std::wstringstream ErrorMsg;
ErrorMsg << L"Parameter 1 sollte > 5 sein, ist aber " << Parameter1 << L"!" << ::std::endl;
Log(ErrorMsg.str());
Code: Alles auswählen
Log << L"Parameter 1 sollte > 5 sein, ist aber " << Parameter1 << L"!" << ::std::endl;
Dass man diese Ausgaben umleiten kann, war mir bin jetzt noch gänzlich unbekannt! Google sagt mir, ich brauche ein eigenes ::std::streambuf-Objekt dafür … ich werde mal schauen, wie ich das hinbekomme, und melde mich bei Problemen wieder. Danke für den Hinweis, das ist schließlich exakt, was ich haben möchte!Biolunar hat geschrieben:Wie wäre es, wenn du std::clog oder std::wclog für deine Ausgaben ummünzt? Dann hättest du immer ein clog << text.str();.
Ich habe mir in der Vermutung, dass es sowas gibt, schon ::std::clog und ::std::cout angeschaut, ihre Implementierung aber nirgendwo gefunden und dann aufgegeben …
Re: [C++] stringstream::flush() überladen
Ja, exakt man brauch einen neuen streambuffer. Mit Hilfe von Boost.IOStreams ist es ziemlich einfach so einen streambuffer zu erstellen oder aber du leitest selber von std::basic_streambuf ab... Du könntest dir z.B. die Implementierung des std::basic_filebuf mal ansehen, da dieser warscheinlich gepuffert ist.
- Krishty
- Establishment
- Beiträge: 8305
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] stringstream::flush() überladen
Zu spät, habe schon meinen eigenen Stream geschrieben. ::std::basic_filebuf nutzt C-Files, die von sich aus schon gepuffert sind und puffert deshalb nicht selbst.
Ich habe für meinen Text einfach einen ::std::vector<wchar_t> genommen. Das Ding ist, dass es mit ::std::wcerr funktioniert, mit ::std::wclog und ::std::wcout allerdings nicht – dort erreicht immernur der zuletzt geschickte Teil der Nachricht sein Ziel … immer, wenn eine Nachricht für den Puffer zu lang ist und einen Aufruf von overflow() provoziert, bleibt der Puffer einfach leer.
Du hast nicht zufällig einen Tipp, warum es mit ::std::wcerr funktioniert und mit den anderen Streams nicht?
Ich habe für meinen Text einfach einen ::std::vector<wchar_t> genommen. Das Ding ist, dass es mit ::std::wcerr funktioniert, mit ::std::wclog und ::std::wcout allerdings nicht – dort erreicht immernur der zuletzt geschickte Teil der Nachricht sein Ziel … immer, wenn eine Nachricht für den Puffer zu lang ist und einen Aufruf von overflow() provoziert, bleibt der Puffer einfach leer.
Du hast nicht zufällig einen Tipp, warum es mit ::std::wcerr funktioniert und mit den anderen Streams nicht?
Re: [C++] stringstream::flush() überladen
Ich kann das Verhalten nicht reproduzieren, mit allen (wcout, wcerr, wclog) funktioniert es bei mir mit dem vector einwandfrei.
Wenn du deine Log-Ausgaben in eine Datei schreiben willst, gibts auch eine einfache Variante ohne einen eigenen streambuffer:Da musst du halt nur in deiner main() ein Logger Objekt erstellen und damit ist für den Rest deines Programms clog und wclog auf die Datei umgeleitet.
Hab ich dich richtig verstanden, dass du deine Ausgabe nur machen willst, wenn der Stream geflusht wird? Also ein beliebig großer Puffer, der *nur* bei einem flush geleert wird? Ich könnt dir mal einen schreiben allerdings frühstens Morgen, denn gleich gehts los zu ner Radtour und dann betrinke ich mich :)
Die Benutzung wird so wie die Klasse Logger (siehe Oben) gehandhabt, nur entfallen logischerweise die beiden file streams. Wenn du doch was anderes meintest, dann gib mal genau deine Wünsche an, damit du mit dem buffer auch glücklich werden kannst :)
Wenn du deine Log-Ausgaben in eine Datei schreiben willst, gibts auch eine einfache Variante ohne einen eigenen streambuffer:
Code: Alles auswählen
class Logger
{
public:
Logger() :
sb(0),
wsb(0),
file("output.txt", std::ios_base::app),
wfile("output.txt", std::ios_base::app)
{
sb = std::clog.rdbuf(file.rdbuf());
wsb = std::wclog.rdbuf(wfile.rdbuf());
}
~Logger()
{
std::clog.rdbuf(sb);
std::wclog.rdbuf(wsb);
}
private:
std::streambuf* sb;
std::wstreambuf* wsb;
std::ofstream file;
std::wofstream wfile;
};
Hab ich dich richtig verstanden, dass du deine Ausgabe nur machen willst, wenn der Stream geflusht wird? Also ein beliebig großer Puffer, der *nur* bei einem flush geleert wird? Ich könnt dir mal einen schreiben allerdings frühstens Morgen, denn gleich gehts los zu ner Radtour und dann betrinke ich mich :)
Die Benutzung wird so wie die Klasse Logger (siehe Oben) gehandhabt, nur entfallen logischerweise die beiden file streams. Wenn du doch was anderes meintest, dann gib mal genau deine Wünsche an, damit du mit dem buffer auch glücklich werden kannst :)
-
- Beiträge: 49
- Registriert: 09.01.2003, 13:04
Re: [C++] stringstream::flush() überladen
Ich habe mir den Thread nicht genau angesehen, aber wenn std::(w)cerr aus der Reihe tanzt, hat das meist damit zu tun, das dieser Ausgabekanal standardmäßig nicht gepuffert ist (im Gegensatz zu std::(w)cout und std::(w)log). Das ist deshalb so, da bei einem Programmabsturz der Pufferinhalt verloren wäre, was in den meisten Fällen nicht das gewünschte Verhalten ist, was man von diesem Ausgabekanal erwartet. Das kann man zwar z. B. mit std::(w)clog umgehen, man sollte sich aber Fragen, ob es wirklich das ist, was man will.Krishty hat geschrieben:Du hast nicht zufällig einen Tipp, warum es mit ::std::wcerr funktioniert und mit den anderen Streams nicht?
Zuletzt geändert von Unknown GER am 13.06.2009, 22:35, insgesamt 1-mal geändert.
-
- Beiträge: 49
- Registriert: 09.01.2003, 13:04
Re: [C++] stringstream::flush() überladen
Sorry, konnte nicht umhin, an der Logger-Beispiel-Klasse etwas umzusortieren (Initialisierungsliste und Reihenfolger der Deklarationen). Die Member file und wfile würden sonst implizit für die Katz in der Initialisierungsliste initialisiert werden und dann im Konstruktor gleich wieder überschrieben.
Code: Alles auswählen
class Logger
{
public:
Logger() :
file("output.txt", std::ios_base::app),
wfile("output.txt", std::ios_base::app),
sb(std::clog.rdbuf(file.rdbuf())),
wsb(std::wclog.rdbuf(wfile.rdbuf()))
{
}
~Logger()
{
std::clog.rdbuf(sb);
std::wclog.rdbuf(wsb);
}
private:
std::ofstream file;
std::wofstream wfile;
std::streambuf* sb;
std::wstreambuf* wsb;
};
- Krishty
- Establishment
- Beiträge: 8305
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] stringstream::flush() überladen
Oha, das Thema habe ich ganz vergessen.
Nun, das Buffered/Unbuffered-Problem war wohl in einem Vertipper im Umgang mit den Datencontainer begründet. Es funktioniert nun soweit. Ich werde meinen Code hier posten, vorher aber noch eine Frage: Kann ich mich darauf verlassen, dass der frisch allokierte Inhalt eines ::std::vector<char> immer genullt ist?
Nun, das Buffered/Unbuffered-Problem war wohl in einem Vertipper im Umgang mit den Datencontainer begründet. Es funktioniert nun soweit. Ich werde meinen Code hier posten, vorher aber noch eine Frage: Kann ich mich darauf verlassen, dass der frisch allokierte Inhalt eines ::std::vector<char> immer genullt ist?
-
- Beiträge: 49
- Registriert: 09.01.2003, 13:04
Re: [C++] stringstream::flush() überladen
Ja, ein std::vector ruft in diesem Fall den Defaultkonstruktor von jedem Element auf. Die "Defaultkonstruktoren" der intrinsischen Datentypen nullen sich selbst.
- Krishty
- Establishment
- Beiträge: 8305
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] stringstream::flush() überladen
Alles klar. Hier ist mein minimalistischer Streambuffer (ohne get-Funktionalität), der alle Strings an den Debugger weiterleitet:
Btw scheinen Links in Code-Kommentaren Probleme zu bereiten …
{code=cpp}// http://www.google.de{/code}
Code: Alles auswählen
inline void ReportToDebugger(const wchar_t p_Text[]) {
// See http:// msdn.microsoft.com/en-us/library/ms680345.aspx.
if(::IsDebuggerPresent())
// See http:// msdn.microsoft.com/en-us/library/aa363362.aspx.
::OutputDebugStringW(p_Text);
return;
}
inline void ReportToDebugger(const char p_Text[]) {
// See http:// msdn.microsoft.com/en-us/library/ms680345.aspx.
if(::IsDebuggerPresent())
// See http:// msdn.microsoft.com/en-us/library/aa363362.aspx.
::OutputDebugStringA(p_Text);
return;
}
// Redirects any output to the debugger.
// Use ::std::ios::rdbuf() to bind this stream buffer to IOstreams like ::std::cout, ::std::cerr or ::std::clog.
template <
typename t_CharacterType,
typename t_CharacterTraits = ::std::char_traits<t_CharacterType>
> class DebuggerStreamBuffer
: public ::std::basic_streambuf<t_CharacterType, t_CharacterTraits>
{
protected:
// Stores the current text until the stream is flushed.
::std::vector<t_CharacterType> m_TextBuffer;
// Prepares the text buffer for new text and abandons its old content.
void ResetBuffer(void) {
// We can not just resize the buffer since its content must be cleared with zeroes.
this->m_TextBuffer.clear();
this->ExtendBuffer();
return;
}
// Reserves memory for further text in the buffer and updates the buffer pointers.
void ExtendBuffer(void) {
static const size_t BufferStepSize = 8;
this->m_TextBuffer.resize(this->m_TextBuffer.size() + BufferStepSize, t_CharacterType(0));
// Set the new memory as the put pointer region. See http:// www. cplusplus.com/reference/iostream/streambuf/setp/.
this->setp(this->m_TextBuffer.end()._Myptr - BufferStepSize, this->m_TextBuffer.end()._Myptr);
return;
}
public:
// Standard constructor.
explicit DebuggerStreamBuffer(void) {
this->ResetBuffer();
return;
}
// This function will be called whenever the text buffer needs further memory.
// See http:// www. cplusplus.com/reference/iostream/streambuf/overflow/.
virtual typename t_CharacterTraits::int_type overflow(
typename t_CharacterTraits::int_type p_Character
) {
// Add the new character.
this->m_TextBuffer.push_back(static_cast<t_CharacterType>(p_Character));
// Reserve space for further text.
this->ExtendBuffer();
// Any value different from EOF makes the caller proceed.
return t_CharacterTraits::not_eof(p_Character);
}
// This function will be called whenever the text buffer is flushed, e.g. when writing ::std::endl or ::std::flush. It
// sends the text to the debugger and clears the buffer.
// See http:// www. cplusplus.com/reference/iostream/streambuf/sync/.
virtual int sync(void) {
// Do not print empty strings.
if(L'\0' == this->m_TextBuffer[0])
return 0;
else {
// Buffered text is never zero-terminated; we must append the zero ourselves.
this->m_TextBuffer.push_back(L'\0');
// Print the old text …
ReportToDebugger(&this->m_TextBuffer[0]);
// … and prepare for new text.
this->ResetBuffer();
// A return value of 0 indicates success.
return 0;
}
}
// Destructor.
virtual ~DebuggerStreamBuffer(void) {
// Flush any remaining text.
this->sync();
return;
}
}; // class DebuggerStreamBuffer
{code=cpp}// http://www.google.de{/code}
Code: Alles auswählen
// http://www.google.de
Zuletzt geändert von Krishty am 14.06.2009, 20:39, insgesamt 2-mal geändert.
- Schrompf
- Moderator
- Beiträge: 4996
- Registriert: 25.02.2009, 23:44
- Benutzertext: Lernt nur selten dazu
- Echter Name: Thomas
- Wohnort: Dresden
- Kontaktdaten:
Re: [C++] stringstream::flush() überladen
Der Default-Konstruktor eines chars tut gar nix. Ein std::vector<char> enthält also Müll, außer Du benutzt explizit den vector-Konstruktor, bei dem Du den Vorgabewert als Parameter angeben kannst:
Code: Alles auswählen
std::vector<char> zeuch( 5000 /* Anzahl Elemente */, 0 /* Vorgabeelement */);
Früher mal Dreamworlds. Früher mal Open Asset Import Library. Heutzutage nur noch so rumwursteln.
-
- Beiträge: 49
- Registriert: 09.01.2003, 13:04
Re: [C++] stringstream::flush() überladen
Wohoo, Tatsache, da hab ich nun echt C# und C++ durcheinandergewürfelt, aber wie Du ja schon gesagt hast gibt es beim Vektorkonstruktor eine entsprechende Variante.
- Krishty
- Establishment
- Beiträge: 8305
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] stringstream::flush() überladen
Danke, habe ich – auch im Beispiel – direkt korrigiert!
Re: [C++] stringstream::flush() überladen
Die umstrukturierung der Klasse "Logger" ist in der Tat sinnvoll danke :), wenn auch aus performance Gründen irrelevant. Also so grausig war das doch nicht oder? ;-)
Da gibt es schon grausigere Sachen wie sowas:
Ich hab den Streambuffer mal umgeschrieben:So wäre der streambuf eigentlich ungepuffert, weil kein interner buffer mit setp() festgelegt worden ist, aber duch den privaten String wird eine dynamische Pufferung vorgenommen. Die Streampuffer sind nämlich nur für Puffer mit fester größe vorgesehen, daher der umweg über den eigenen String.
Da gibt es schon grausigere Sachen wie sowas:
Das void in der Parameterliste ist redundant und in C++ nicht gerne gesehen. Außerdem hat das explicit an dieser Stelle keine Wirkung.Krishty hat geschrieben:Code: Alles auswählen
// Standard constructor. explicit DebuggerStreamBuffer(void) { this->ResetBuffer(); return; }
Implementationsabhängig: Wo steht denn, dass ein std::vector<...>::iterator eine Variable namens _Myptr hat? Wenn, dann lieber &m_TextBuffer[0], da das seit C++03 ein definiertes (zusammenhängendes!) Array ergibt. (Hast du auch korrekt in der sync() Elementfunktion angewendet)Krishty hat geschrieben:Code: Alles auswählen
// Reserves memory for further text in the buffer and updates the buffer pointers. void ExtendBuffer(void) { static const size_t BufferStepSize = 8; this->m_TextBuffer.resize(this->m_TextBuffer.size() + BufferStepSize); // Set the new memory as the put pointer region. See http:// www. cplusplus.com/reference/iostream/streambuf/setp/. this->setp(this->m_TextBuffer.end()._Myptr - BufferStepSize, this->m_TextBuffer.end()._Myptr, t_CharacterType(0)); return; }
Ich hab den Streambuffer mal umgeschrieben:
Code: Alles auswählen
// Die beiden Änderungen mussten sein, weil ich kein VS verwende
void ReportToDebugger(char const* str)
{
std::ofstream file("output.txt", std::ios_base::app);
file << str;
}
void ReportToDebugger(wchar_t const* str)
{
std::wofstream file("output.txt", std::ios_base::app);
file << str;
}
template <typename char_t, typename traits_t = std::char_traits<char_t> >
class logbuf : public std::basic_streambuf<char_t, traits_t>
{
public:
typedef std::basic_streambuf<char_t, traits_t> base_class;
typedef typename base_class::char_type char_type;
typedef typename base_class::traits_type traits_type;
typedef typename base_class::int_type int_type;
logbuf()
{
reset();
}
protected:
virtual int sync()
{
try
{
ReportToDebugger(buffer.c_str());
reset();
}
catch (...)
{
return -1;
}
return 0;
}
virtual int_type overflow(int_type c = traits_type::eof())
{
if (traits_type::eq_int_type(c, traits_type::eof()))
sync(); // return value omitted
else
buffer.push_back(c);
return traits_type::not_eof(c);
}
private:
void reset()
{
buffer.clear();
buffer.reserve(magic_size); // Prevent frequent reallocations
}
typedef std::basic_string<char_type, traits_type> string_type;
static typename string_type::size_type const magic_size = 32;
string_type buffer;
};
class Logger
{
public:
Logger() :
sb(std::clog.rdbuf(&narrow)),
wsb(std::wclog.rdbuf(&wide))
{
}
~Logger()
{
std::clog.rdbuf(sb);
std::wclog.rdbuf(wsb);
}
private:
logbuf<char> narrow;
logbuf<wchar_t> wide;
std::streambuf* sb;
std::wstreambuf* wsb;
};
- Krishty
- Establishment
- Beiträge: 8305
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] stringstream::flush() überladen
Autsch, voll in ein Newbie-Fettnäpfchen getreten :DBiolunar hat geschrieben:Das void in der Parameterliste ist redundant und in C++ nicht gerne gesehen.
Stimmt … Gewohnheit :roll:Biolunar hat geschrieben:Außerdem hat das explicit an dieser Stelle keine Wirkung.
Das geht an der Stelle eher schlecht als Recht – auf end() kann man nicht per operator [] zugreifen, weil sonst korrekterweise eine vector-subscript-out-of-range-Assertion hochgeht. Das wird dann zu &this->m_TextBuffer[0] + this->m_TextBuffer.size() … wäre &*this->m_TextBuffer.end() eine Möglichkeit, oder geht es noch besser?Implementationsabhängig: Wo steht denn, dass ein std::vector<...>::iterator eine Variable namens _Myptr hat? Wenn, dann lieber &m_TextBuffer[0], da das seit C++03 ein definiertes (zusammenhängendes!) Array ergibt. (Hast du auch korrekt in der sync() Elementfunktion angewendet)
Zu deinem Code: Was ist der Vorteil von ::std::basic_string (habe ich in der Doku nicht finden können)? Auch gut zu wissen, dass ich in overflow() auf ein mögliches eof achten muss.
So hatte ich es gemacht, als meine Pufferung nicht funktionierte und ich keinen Bock auf Debugging hatte :DBiolunar hat geschrieben:So wäre der streambuf eigentlich ungepuffert, weil kein interner buffer mit setp() festgelegt worden ist, aber duch den privaten String wird eine dynamische Pufferung vorgenommen.
Re: [C++] stringstream::flush() überladen
Wus? Kommt dir das bekannt vor:Krishty hat geschrieben:Zu deinem Code: Was ist der Vorteil von ::std::basic_string (habe ich in der Doku nicht finden können)?
Code: Alles auswählen
namespace std
{
typedef basic_string<char> string;
}
Ich seh grad du übergibst setp() drei Argumente??? Jetzt bin ich verwirrt; das nimmt doch nur zwei :?: Da du sowieso einen vector verwendest, kannst du dir die interne Pufferung des streambuffers sowieso sparen (siehe mein Code). Damit entfällt auch die Notwendigkeit für setp, also keine Iteratorverunstaltung mehr :)
- Krishty
- Establishment
- Beiträge: 8305
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] stringstream::flush() überladen
Okay, das erklärt einiges.Biolunar hat geschrieben:Ja! Std::string ist ein std::basic_string!
Ich bin in der Zeile verrutscht, als ich nachgebessert habe, dass der Vektor mit Nullen gefüllt werden soll. Ist korrigiert.Biolunar hat geschrieben:Ich seh grad du übergibst setp() drei Argumente??? Jetzt bin ich verwirrt; das nimmt doch nur zwei :?:
Ich hatte mir gedacht, dass die Möglichkeit zum direkten Schreiben in den Puffer schneller ist, als für jeden Buchstaben overflow() aufzurufen.Biolunar hat geschrieben:Da du sowieso einen vector verwendest, kannst du dir die interne Pufferung des streambuffers sowieso sparen (siehe mein Code). Damit entfällt auch die Notwendigkeit für setp, also keine Iteratorverunstaltung mehr :)
- Aramis
- Moderator
- Beiträge: 1458
- Registriert: 25.02.2009, 19:50
- Echter Name: Alexander Gessler
- Wohnort: 2016
- Kontaktdaten:
Re: [C++] stringstream::flush() überladen
Ich hab mal gehört, dass der C++-Sprachstandard bei so manchem eine Antwort bereit hält, u.A. die finale Antwort auf die Frage nach der Standardisierung mancher Funktionen, den Klassen der Standardbibliothek, und dem ganzen Rest :twisted:
*Zieht Kopf zurück und versteckt sich im Keller* :(
*Zieht Kopf zurück und versteckt sich im Keller* :(
Re: [C++] stringstream::flush() überladen
Man könnte zusätzlich noch das xsputn() überschreiben:
Dann wird halt nicht so oft overflow() aufgerufen, sondern pro String einmal xsputn().
Code: Alles auswählen
virtual std::streamsize xsputn(char_type const* str, std::streamsize n)
{
typename string_type::size_type const old_size = buffer.size();
try
{
buffer.append(str, n);
}
catch (...)
{
return buffer.size() - old_size;
}
return n;
}
- Krishty
- Establishment
- Beiträge: 8305
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [C++] stringstream::flush() überladen
Optimal – danke!