<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Code für Ausgabe vereinfachen.]]></title><description><![CDATA[<p>Hi!<br />
Ich möchte Ausgaben aus unterschiedlichen Datentypen erzeugen.</p>
<p>Soweit habe ich es schon:</p>
<pre><code class="language-cpp">string mk_str ( stringstream&amp; stream )
{
    return stream.str();   
}
stringstream stream;
stream &lt;&lt; &quot;a&quot; &lt;&lt; 2 &lt;&lt; &quot;b&quot; &lt;&lt; 3.3 &lt;&lt; endl;
cout &lt;&lt; mk_str(stream);
</code></pre>
<p>Schöner wäre es, wenn ich daraus eine Zeile machen könnte.<br />
Ich habe</p>
<pre><code class="language-cpp">cout &lt;&lt; mk_str(stream &lt;&lt; &quot;a&quot; &lt;&lt; 2);
</code></pre>
<p>probiert, aber es kommt der Fehler</p>
<blockquote>
<p>Konvertierung des Parameters 1 von 'std::basic_ostream&lt;_Elem,_Traits&gt;' in 'std::stringstream &amp;' nicht möglich</p>
</blockquote>
<p>Muss ich das mit ner Ellipse machen oder so?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/245524/code-für-ausgabe-vereinfachen</link><generator>RSS for Node</generator><lastBuildDate>Fri, 18 Sep 2026 15:38:08 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/245524.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 15 Jul 2009 08:45:30 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 08:45:30 GMT]]></title><description><![CDATA[<p>Hi!<br />
Ich möchte Ausgaben aus unterschiedlichen Datentypen erzeugen.</p>
<p>Soweit habe ich es schon:</p>
<pre><code class="language-cpp">string mk_str ( stringstream&amp; stream )
{
    return stream.str();   
}
stringstream stream;
stream &lt;&lt; &quot;a&quot; &lt;&lt; 2 &lt;&lt; &quot;b&quot; &lt;&lt; 3.3 &lt;&lt; endl;
cout &lt;&lt; mk_str(stream);
</code></pre>
<p>Schöner wäre es, wenn ich daraus eine Zeile machen könnte.<br />
Ich habe</p>
<pre><code class="language-cpp">cout &lt;&lt; mk_str(stream &lt;&lt; &quot;a&quot; &lt;&lt; 2);
</code></pre>
<p>probiert, aber es kommt der Fehler</p>
<blockquote>
<p>Konvertierung des Parameters 1 von 'std::basic_ostream&lt;_Elem,_Traits&gt;' in 'std::stringstream &amp;' nicht möglich</p>
</blockquote>
<p>Muss ich das mit ner Ellipse machen oder so?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743290</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743290</guid><dc:creator><![CDATA[print0r]]></dc:creator><pubDate>Wed, 15 Jul 2009 08:45:30 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 08:49:45 GMT]]></title><description><![CDATA[<p>Mach doch einfach <code>cout &lt;&lt; &quot;a&quot; &lt;&lt; 2 &lt;&lt; &quot;b&quot; &lt;&lt; 3.3 &lt;&lt; endl;</code> <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743292</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743292</guid><dc:creator><![CDATA[Badestrand]]></dc:creator><pubDate>Wed, 15 Jul 2009 08:49:45 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 08:51:24 GMT]]></title><description><![CDATA[<p>Das geht leider nicht, es gibt eine 'zentrale' Ausgabefunktion, die einen 'fertigen' string erwartet.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743294</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743294</guid><dc:creator><![CDATA[print0r]]></dc:creator><pubDate>Wed, 15 Jul 2009 08:51:24 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 08:57:07 GMT]]></title><description><![CDATA[<p>print0r schrieb:</p>
<blockquote>
<p>Das geht leider nicht, es gibt eine 'zentrale' Ausgabefunktion, die einen 'fertigen' string erwartet.</p>
</blockquote>
<p>Zeig doch mal! Was macht eine &quot;zentrale Ausgabefunktion&quot;? Die gibt doch auch nur den String aus ... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743297</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743297</guid><dc:creator><![CDATA[Pigeon]]></dc:creator><pubDate>Wed, 15 Jul 2009 08:57:07 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 09:09:44 GMT]]></title><description><![CDATA[<p>Ja, genau, die zentrale Augabefunktion holt die Übersetzung des String und leitet den String weiter:</p>
<pre><code class="language-cpp">void print(string s)
{
  string msg = get_message(s); // Übersetzung holen.
#ifdef LINUX 
cout &lt;&lt; s; // Ausgabe Linuxkonsole
#endif

#ifdef WINDOWS
print_rich_edit_control(s); // Ausgabe Windows.
#endif

}
</code></pre>
<p>Ich portiere mein Projekt von C nach C++, in C habe ich die Aufgabe so gelöst:</p>
<pre><code class="language-cpp">char msgbuf[1024];
char* msg_mk ( char* a, ... )
{
	va_list v;
	va_start(v,a);
	vsnprintf ( msgbuf, sizeof(msgbuf) / sizeof(*msgbuf) -1, a, v );
	va_end(v); 
	return msgbuf;
}
print( msg_mk ( &quot;%s%d%s%d%s\n&quot;, &quot;Cr&quot;, 3, &quot;at&quot;, 0, &quot;r&quot; ));
</code></pre>
<p>Ich dachte mir, von der Codeästhetik her betrachtet, wäre es besser von char* auf string zu wechseln.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743310</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743310</guid><dc:creator><![CDATA[print0r]]></dc:creator><pubDate>Wed, 15 Jul 2009 09:09:44 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 09:13:09 GMT]]></title><description><![CDATA[<p>Im obigen Bespiel müssen die zeilen natürlich</p>
<pre><code class="language-cpp">#ifdef LINUX 
cout &lt;&lt; msg; // Ausgabe Linuxkonsole 
#endif 

#ifdef WINDOWS 
print_rich_edit_control(msg); // Ausgabe Windows. 
#endif
</code></pre>
<p>heißen. Ist aber für mein Problem nicht relevant.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743312</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743312</guid><dc:creator><![CDATA[print0r]]></dc:creator><pubDate>Wed, 15 Jul 2009 09:13:09 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 09:31:40 GMT]]></title><description><![CDATA[<p>Du könntest ein template schreiben:</p>
<pre><code class="language-cpp">template&lt;typename T&gt;
std::string str(T typ)
{
    stringstream str;
    //Umwandeln ...
}
</code></pre>
<p>Und dies deiner Funktion mit Variabler Anzahl von parametern übergeben:</p>
<pre><code class="language-cpp">print(int Anzahl, .... )
{
   //Hier wie printf arbeiten, nur dass der Typ der Argumente (string) bekannt ist
}

//So dann benutzen:
print( str(3.0), &quot;Hallo&quot;, str(123) );
</code></pre>
<p>Wie wär das? <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":confused:"
      alt="😕"
    /></p>
<p>//Edit: Audacia macht es natürlich sehr viel schöner. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743318</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743318</guid><dc:creator><![CDATA[Pigeon]]></dc:creator><pubDate>Wed, 15 Jul 2009 09:31:40 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 09:29:14 GMT]]></title><description><![CDATA[<p>print0r schrieb:</p>
<blockquote>
<p>Ich portiere mein Projekt von C nach C++, in C habe ich die Aufgabe so gelöst:</p>
<pre><code class="language-cpp">char msgbuf[1024];
char* msg_mk ( char* a, ... )
{
	va_list v;
	va_start(v,a);
	vsnprintf ( msgbuf, sizeof(msgbuf) / sizeof(*msgbuf) -1, a, v );
	va_end(v); 
	return msgbuf;
}
print( msg_mk ( &quot;%s%d%s%d%s\n&quot;, &quot;Cr&quot;, 3, &quot;at&quot;, 0, &quot;r&quot; ));
</code></pre>
<p>Ich dachte mir, von der Codeästhetik her betrachtet, wäre es besser von char* auf string zu wechseln.</p>
</blockquote>
<p>Sicherlich, aber dann verwende doch so etwas, anstatt dich mit Streams herumzuquälen:</p>
<pre><code class="language-cpp">std::string str_printf (const char* format, ...)
{
    std::va_list args;
    std::string retval;

    va_start (args, format);
    retval.resize (std::vsnprintf (0, 0, format, args));
    std::vsnprintf (&amp;retval[0], retval.size () + 1, format, args);
    va_end (args);

    return retval;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1743321</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743321</guid><dc:creator><![CDATA[audacia]]></dc:creator><pubDate>Wed, 15 Jul 2009 09:29:14 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 09:42:03 GMT]]></title><description><![CDATA[<p>... oder so:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;sstream&gt;

/// anything to string
class a2str
{
  std::stringstream ss;
public:
  template&lt;typename T&gt;
  a2str&amp; operator&lt;&lt;(T const&amp; x) { ss&lt;&lt;x; return *this; }
  operator std::string() const { return ss.str(); }
};

int main()
{
  int i = 23;
  std::string s = a2str() &lt;&lt; &quot;mein i ist &quot; &lt;&lt; i &lt;&lt; &quot;.&quot;;
  std::cout &lt;&lt; s &lt;&lt; '\n';
}
</code></pre>
<p>Gruß,<br />
SP</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743330</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743330</guid><dc:creator><![CDATA[Sebastian Pizer]]></dc:creator><pubDate>Wed, 15 Jul 2009 09:42:03 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 09:47:18 GMT]]></title><description><![CDATA[<p>Pigeon schrieb:</p>
<blockquote>
<p>Du könntest ein template schreiben [...] Und dies deiner Funktion mit Variabler Anzahl von parametern übergeben:</p>
<pre><code class="language-cpp">template&lt;typename T&gt;
std::string str(T typ);

// ...

print(int Anzahl, ... )
{
   // Hier wie printf arbeiten, nur dass der Typ der Argumente
   // (string) bekannt ist
}
</code></pre>
</blockquote>
<p>Das mit den variadischen Funktionen funktioniert nur für PODs (plain old data structures). std::string ist kein POD. Dieses Sprachmerkmal (&quot;...&quot;) ist <em>sooo</em> unattraktiv, dass ich gar nicht weiß, wie man es richtig benutzen müsste. :p</p>
<p>Gruß,<br />
SP</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743334</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743334</guid><dc:creator><![CDATA[Sebastian Pizer]]></dc:creator><pubDate>Wed, 15 Jul 2009 09:47:18 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 09:49:29 GMT]]></title><description><![CDATA[<p>Sebastian Pizer schrieb:</p>
<blockquote>
<p>Das mit den variadischen Funktionen funktioniert nur für PODs (plain old data structures). std::string ist kein POD. Dieses Sprachmerkmal (&quot;...&quot;) ist <em>sooo</em> unattraktiv, dass ich gar nicht weiß, wie man es richtig benutzen müsste. :p</p>
<p>Gruß,<br />
SP</p>
</blockquote>
<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /> Wieder was gelernt. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743336</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743336</guid><dc:creator><![CDATA[Pigeon]]></dc:creator><pubDate>Wed, 15 Jul 2009 09:49:29 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 10:30:58 GMT]]></title><description><![CDATA[<p>Pigeon schrieb:</p>
<blockquote>
<p>//Edit: Audacia macht es natürlich sehr viel schöner. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
</blockquote>
<p>Mach dir nix draus, auf den Code von Audacia wäre ich auch in meinen kühnsten Träumen nicht gekommen!<br />
Vor allem nicht auf die Zeilen:</p>
<pre><code class="language-cpp">retval.resize (vsnprintf (0, 0, format, args)); 
	vsnprintf (&amp;retval[0], retval.size () + 1, format, args);  :open_mouth:
</code></pre>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/8276">@Audacia</a>:</p>
<pre><code class="language-cpp">cout &lt;&lt; str_printf ( &quot;%s%d%s\n&quot;, &quot;str_printf ist &quot;, 1, &quot;A!&quot; );
</code></pre>
<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/36159">@Sebastian</a> Pizer<br />
Ebenfalls ne 1A Variante, die ich (noch nicht ganz) kapiere aber die ich so benutzen kann:</p>
<pre><code class="language-cpp">cout &lt;&lt; (s = a2str() &lt;&lt; &quot;Meine &quot; &lt;&lt; 6 &lt;&lt; &quot; Frauen sind super!&quot;)
;
</code></pre>
<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
<p>Pigeon schrieb:</p>
<blockquote>
<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /> Wieder was gelernt. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f61e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--disappointed_face"
      title=":("
      alt="😞"
    /></p>
</blockquote>
<p>Warum machst du so ein Gesicht? Freu dich doch, das du dazugelernt hast. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /><br />
Das nächste mal bist <strong>du</strong> derjenige, der die beste Lösung vorschlägt.<br />
Würde ich jedes mal so ein Gesicht machen, wenn ich etwas dazulerne, wäre mein Kinn schon blutig gescheuert vom auf dem Boden schleifen. :p</p>
<p>So, ich muss jetzt erstmal leider Feierabend machen und ab gehts zum Baden in die Sonne!<br />
Vielen Dank allen beteiligten! <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /><br />
<img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743367</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743367</guid><dc:creator><![CDATA[print0r]]></dc:creator><pubDate>Wed, 15 Jul 2009 10:30:58 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 12:28:07 GMT]]></title><description><![CDATA[<p>Sebastian Pizer schrieb:</p>
<blockquote>
<p>Das mit den variadischen Funktionen funktioniert nur für PODs (plain old data structures). std::string ist kein POD. Dieses Sprachmerkmal (&quot;...&quot;) ist <em>sooo</em> unattraktiv, dass ich gar nicht weiß, wie man es richtig benutzen müsste. :p</p>
</blockquote>
<p>Da muss ich mich anschliessen. Mir gefällt aber audacias Code auch sonst nicht besonders... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Was spricht gegen eine Klasse, die den <code>operator&lt;&lt;</code> anbietet und dessen Aufrufe an die Systemfunktionen weiterleitet?</p>
<pre><code class="language-cpp">struct endl_t {} endl; // führt zum Weiterleiten ans System

class streamer
{
    public:
        template &lt;typename T&gt;
        streamer&amp; operator&lt;&lt; (const T&amp; value)
        {
            m_stream &lt;&lt; value;
            return *this;
        }

        streamer&amp; operator&lt;&lt; (const endl_t&amp;)
        {
            system_output(m_stream.str());
            m_stream.str(&quot;&quot;);
            return *this;
        }

    private:
        void system_output(const std::string&amp; message)
        {
            // tue je nach System etwas anderes
        }

    private:
        std::stringstream m_stream;
};
</code></pre>
<p>Anwendung:</p>
<pre><code class="language-cpp">streamer s;
s &lt;&lt; &quot;Hallo&quot; &lt;&lt; 43 &lt;&lt; endl;
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/1743469</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743469</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Wed, 15 Jul 2009 12:28:07 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 13:44:48 GMT]]></title><description><![CDATA[<p>Nexus schrieb:</p>
<blockquote>
<p>Mir gefällt aber audacias Code auch sonst nicht besonders... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
</blockquote>
<p>Wenn du etwas konkreter wärest, könnte man fast meinen, daß du auch einen Grund dafür hättest.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743529</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743529</guid><dc:creator><![CDATA[audacia]]></dc:creator><pubDate>Wed, 15 Jul 2009 13:44:48 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 14:36:49 GMT]]></title><description><![CDATA[<p>Muss man das noch begründen?</p>
<p>Ok, wie wär's mit:<br />
- VarArgs sind typunsicher<br />
- VarArgs funktionieren nur für PODs<br />
- VarArgs erlauben dir hier nicht, beliebige benutzerdefinierte Typen T zu unterstützen, für die es einen operator&lt;&lt;(ostream&amp;, const T&amp;) gibt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743583</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743583</guid><dc:creator><![CDATA[Sebastian Pizer]]></dc:creator><pubDate>Wed, 15 Jul 2009 14:36:49 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 14:42:30 GMT]]></title><description><![CDATA[<p>audacia schrieb:</p>
<blockquote>
<p>Nexus schrieb:</p>
<blockquote>
<p>Mir gefällt aber audacias Code auch sonst nicht besonders... <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
</blockquote>
<p>Wenn du etwas konkreter wärest, könnte man fast meinen, daß du auch einen Grund dafür hättest.</p>
</blockquote>
<p>Der Code ist sicherlich gute für seinen bestimmten Anwendungszweck, lässt für den &quot;modernen&quot; Einsatz aber vermissen, eigene Objekte zu verwenden, bei denen z.B. <code>ostream&amp; operator&lt;&lt;( ostream&amp; o, const T&amp; elem )</code> überladen ist.</p>
<p>Den Anwendungsfall des OP gibt es ja in mehreren Projekten, da ziehe ich eigentlich immer einen eigenen streambuf für cout/cerr vor, der bei einem flush (also auch endl) den Text überträgt/behandelt. Das eignet sich nur leider nicht für Internationalisierung à la gettext.<br />
Internationalisierung hatte ich sowieso erst in einem einzigen Projekt (und dann noch in einem privaten), da hatte ich das etwa so gelöst:</p>
<pre><code class="language-cpp">// Im Code:
std::string error_text = makeError( &quot;BlaNotFound&quot;, obj1, obj2, obj3, ... );

// In der Sprach-Datei (.txt-Datei):
BlaNotFound: Object %1 could not be found in area %3 where %2=%4
...
</code></pre>
<p>&quot;makeError&quot; hat die Objekte dann per stringstream in Strings umgewandelt und in den Sprach-String eingefügt.</p>
<p>edit: Alter, über 5 Minuten für einen Post <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f615.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--confused_face"
      title=":-/"
      alt="😕"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743590</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743590</guid><dc:creator><![CDATA[Badestrand]]></dc:creator><pubDate>Wed, 15 Jul 2009 14:42:30 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 14:51:18 GMT]]></title><description><![CDATA[<p>Sebastian Pizer schrieb:</p>
<blockquote>
<p>Muss man das noch begründen?</p>
</blockquote>
<p>Daß &quot;echte C++-Programmierer&quot; variadische Funktionen als Teufelszeug empfinden, ist mir bekannt. Interessiert wäre ich eher an einer Erklärung des &quot;auch sonst&quot;.</p>
<p>Sebastian Pizer schrieb:</p>
<blockquote>
<p>- VarArgs sind typunsicher</p>
</blockquote>
<p>Es ist aber problemlos möglich, die Funktionen z.B. im Debug-Build durch typsichere zu ersetzen.</p>
<p>Sebastian Pizer schrieb:</p>
<blockquote>
<p>- VarArgs funktionieren nur für PODs<br />
- VarArgs erlauben dir hier nicht, beliebige benutzerdefinierte Typen T zu unterstützen, für die es einen operator&lt;&lt;(ostream&amp;, const T&amp;) gibt.</p>
</blockquote>
<p>Das sind die klassischen Argumente für C++-Streams. Nur sind C++-Streams trotz aller Vorteile in der Theorie IMHO die schlechteste aller Alternativen; mit z.B. boost::format gibt es deutlich sinvollere.</p>
<p>Es hat schon einen Grund, daß keine Sprache außer C++ sich auf so etwas abstruses wie diese Streams einläßt. In allen vernünftigen Sprachen existiert printf() oder eine vergleichbare Alternative.</p>
<p>Badestrand schrieb:</p>
<blockquote>
<p>Der Code ist sicherlich gute für seinen bestimmten Anwendungszweck</p>
</blockquote>
<p>Eben. Darum ging es.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743593</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743593</guid><dc:creator><![CDATA[audacia]]></dc:creator><pubDate>Wed, 15 Jul 2009 14:51:18 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 18:51:48 GMT]]></title><description><![CDATA[<p>audacia schrieb:</p>
<blockquote>
<p>Daß &quot;echte C++-Programmierer&quot; variadische Funktionen als Teufelszeug empfinden, ist mir bekannt. Interessiert wäre ich eher an einer Erklärung des &quot;auch sonst&quot;.</p>
</blockquote>
<p>Ich sagte extra &quot;mir gefällt&quot; und nicht etwa &quot;audacias Code ist&quot;, es handelt sich also um eine subjektive Ansicht. Ich bin nicht unbedingt ein Fan von den C-Formatfunktionen und VarArgs. Aber auch das finde ich beispielsweise nicht allzu toll, da du hier davon ausgehst, dass der <code>std::string</code> an einem Stück sein muss, was nicht garantiert ist:</p>
<pre><code class="language-cpp">&amp;retval[0]
</code></pre>
<p>Und <code>std::vsnprintf</code> ist nicht wirklich im Standard, sondern eher eine sicherere Version von <code>std::vsprintf</code> , oder?</p>
<p>audacia schrieb:</p>
<blockquote>
<p>Nur sind C++-Streams trotz aller Vorteile in der Theorie IMHO die schlechteste aller Alternativen; [...]</p>
<p>Es hat schon einen Grund, daß keine Sprache außer C++ sich auf so etwas abstruses wie diese Streams einläßt. In allen vernünftigen Sprachen existiert printf() oder eine vergleichbare Alternative.</p>
</blockquote>
<p>Ja, so langsam wissen wir, dass dir die C++-Streams nicht gefallen. Du musst sie trotzdem nicht so darstellen, als ob man kaum mit ihnen arbeiten könnte, als ob sie die reinste Hölle wären. Sie sind vielleicht nicht der Höhepunkt der Ein-/Ausgabeprogrammierung, aber als so schlimm empfinde ich sie bei weitem nicht. Ich persönlich finde es sogar angenehmer, mit überladenem <code>operator&lt;&lt;</code> zu arbeiten. Mir sind Typsicherheit und leichte Erweiterbarkeit für eigene Typen auch wichtig. Klar sehe ich auch ein, dass die Streams einige Nachteile haben, aber diese sind momentan nicht derart bedrückend, dass ich lieber auf dem C-Level arbeite. Das ist natürlich Geschmackssache und hängt von den jeweiligen Anforderungen ab...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743742</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743742</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Wed, 15 Jul 2009 18:51:48 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 20:41:25 GMT]]></title><description><![CDATA[<p>Nexus schrieb:</p>
<blockquote>
<p>Aber auch das finde ich beispielsweise nicht allzu toll, da du hier davon ausgehst, dass der <code>std::string</code> an einem Stück sein muss, was nicht garantiert ist</p>
</blockquote>
<p>ISO/IEC 14882 schrieb:</p>
<blockquote>
<p><strong>§21.3.4 basic_string element access</strong><br />
`const_reference operator[](size_type pos) const;</p>
<p>reference operator[](size_type pos);<code>Returns: If</code>pos &lt; size()<code>, returns</code>data()[pos]<code>. Otherwise, if</code>pos == size()<code>, the const version returns</code>charT()` . Otherwise, the behavior is undefined.</p>
</blockquote>
<p>Da <code>basic_string::data()</code> einen Zeiger zurückgibt, impliziert das, daß die Daten linear vorliegen. Es sei natürlich denn, ich übersehe etwas.</p>
<p>Nexus schrieb:</p>
<blockquote>
<p>Und <code>std::vsnprintf</code> ist nicht wirklich im Standard, sondern eher eine sicherere Version von <code>std::vsprintf</code> , oder?</p>
</blockquote>
<p>Soweit ich weiß, ist sie Teil von C99, und zwar ein Teil, den fast alle C++-Compiler implementieren.</p>
<p>Nexus schrieb:</p>
<blockquote>
<p>Ja, so langsam wissen wir, dass dir die C++-Streams nicht gefallen. Du musst sie trotzdem nicht so darstellen, als ob man kaum mit ihnen arbeiten könnte, als ob sie die reinste Hölle wären.</p>
</blockquote>
<p>Du beliebst maßlos zu übertreiben. Ich bemängele lediglich, daß sie stets als unumgänglich bessere Alternative dargestellt werden.</p>
<p>Nexus schrieb:</p>
<blockquote>
<p>Das ist natürlich Geschmackssache und hängt von den jeweiligen Anforderungen ab...</p>
</blockquote>
<p>So ist es. Die Anforderung war hier die einfache Portierung von C-Code.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743798</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743798</guid><dc:creator><![CDATA[audacia]]></dc:creator><pubDate>Wed, 15 Jul 2009 20:41:25 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 21:01:02 GMT]]></title><description><![CDATA[<p>audacia schrieb:</p>
<blockquote>
<p>Daß &quot;echte C++-Programmierer&quot; variadische Funktionen als Teufelszeug empfinden, ist mir bekannt. Interessiert wäre ich eher an einer Erklärung des &quot;auch sonst&quot;.</p>
</blockquote>
<p>Ich bin doch ein &quot;echter C++ Programmierer&quot;, zumindest schimpft man mich immer wieder als viel zu C++ treu, und ich könnte nicht ohne variadische Funktionen leben!<br />
Wieso? Na deswegen:</p>
<pre><code class="language-cpp">typedef char False;
typedef struct { False dummy[2]; } True;

template&lt;typename FromT, typename ToT&gt;
struct IsConvertible
{
private:
  True test(ToT const&amp;);
  False test(...); // &lt;---------
  FromT make();

public:
  static bool const RESULT = sizeof(True) == sizeof(test(make()));
  static bool const IS_SAME = false;
};

template&lt;typename SameT&gt;
struct IsConvertible&lt;SameT, SameT&gt;
{
  static bool const RESULT = true;
  static bool const IS_SAME = true;
};
</code></pre>
<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
<p>Für etwas anderes, würde ich allerdings echt keine variadische Funktionen nehmen, also um solche Funktionen richtig aufzurufen. Ist mir viel zu unsicher. Ich habe sie ein paar Male verwenden wollen und immer ist mir irgendwo ein Fehler unterlaufen. Fängt bei kleinen Dingen an, wie zum Beispiel:</p>
<pre><code class="language-cpp">void fooFloats(std::size_t count, ...)
{
  va_list list;
  va_start(list, count);

  for(std::size_t a = 0; a &lt; count; ++a)
  {
    float f = va_arg(list, float);
    // mach was mit f.
  }

  va_end(list);
}

// ...
fooFloats(5, 3.2, 234.0, 23, 23.0);
// Alle Argumente sind falsch.
</code></pre>
<p>Falsche Anzahl und (double, double, int, double), statt (float, float, float, float). Ein Fehler passiert einfach viel zu schnell. Aber wer mit dem Risiko leben kann ...</p>
<p>Da würde ich es eher über Proxies lösen, wie es auch Boost.Format gemacht hat.<br />
Variadische Funktionen werde ich erst mit dem nächsten Standard anfangen zu verwenden, da man diese dann über Variadic Templates typsicher machen kann.</p>
<p>audacia schrieb:</p>
<blockquote>
<p>Da basic_string::data() einen Zeiger zurückgibt, impliziert das, daß die Daten linear vorliegen. Es sei natürlich denn, ich übersehe etwas.</p>
</blockquote>
<p>Die Daten liegen zwar linear in diesem Pointer, aber wohin der Pointer zeigt, ist nicht definiert. Grundsätzlich darf hier ein neues Array angelegt werden, welches linear ist, während die interne Repräsentation nicht linear ist.</p>
<p>Dazu kannst du zum Beispiel dies hier lesen:</p>
<blockquote>
<p>References, pointers, and iterators referring to the elements of a basic_string sequence may be invalidated by the following uses of that basic_string object:<br />
— As an argument to non-member functions swap() (21.3.7.8), operator&gt;&gt;() (21.3.7.9), and getline() (21.3.7.9).<br />
— As an argument to basic_string::swap().<br />
<strong>— Calling data() and c_str() member functions.</strong><br />
— Calling non-const member functions, except operator[](), at(), begin(), rbegin(), end(), and rend().<br />
— Subsequent to any of the above uses except the forms of insert() and erase() which return iterators, the first call to non-const member functions operator[](), at(), begin(), rbegin(), end(), or rend().</p>
</blockquote>
<p>Der zurückgegeben Pointer kann also invalidiert werden, wenn man erneut data aufruft. Also kann es sich um einen anderen Pointer handeln. Ich kenne zwar keine Standardbibliothek, welche dies wirklich so anwendet. Im nächsten Standard wird dies glaub ich sogar korrigiert.</p>
<p>Grüssli</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743809</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743809</guid><dc:creator><![CDATA[Dravere]]></dc:creator><pubDate>Wed, 15 Jul 2009 21:01:02 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 21:38:32 GMT]]></title><description><![CDATA[<p>Dravere schrieb:</p>
<blockquote>
<p>audacia schrieb:</p>
<blockquote>
<p>Da basic_string::data() einen Zeiger zurückgibt, impliziert das, daß die Daten linear vorliegen. Es sei natürlich denn, ich übersehe etwas.</p>
</blockquote>
<p>Die Daten liegen zwar linear in diesem Pointer, aber wohin der Pointer zeigt, ist nicht definiert. Grundsätzlich darf hier ein neues Array angelegt werden, welches linear ist, während die interne Repräsentation nicht linear ist.</p>
</blockquote>
<p>Du vergißt, daß ich den Wert der darunterliegenden Zeichens verändern darf. Eine Implementation, bei der meine obige Annahme nicht zutrifft, müßte also so aussehen:</p>
<pre><code class="language-cpp">template &lt;typename CharT&gt;
    class basic_string
{
private:
    CharT* actualData;
    CharT* consecutiveData;
    int lastRequestedChar;

    void applyCharModifications (void)
    {
        if (lastRequestedChar &gt;= 0)
        {
            actualData[lastRequestedChar] = consecutiveData[lastRequestedChar];
            lastRequestedChar = -1;
        }
    }
public:
    const CharT* data (void) const
    {
        applyCharModifications ();
        delete consecutiveData;
        consecutiveData = new CharT[size () + 1];
        memcpy (consecutiveData, actualData, sizeof (CharT) * (size() + 1));
        return consecutiveData;
    }
    CharT&amp; operator [] (unsigned idx)
    {
        applyCharModifications ();
        return const_cast &lt;CharT*&gt; (data ())[idx];
    }
    ...
};
</code></pre>
<p>Dravere schrieb:</p>
<blockquote>
<p>Dazu kannst du zum Beispiel dies hier lesen:</p>
<blockquote>
<p>References, pointers, and iterators referring to the elements of a basic_string sequence may be invalidated by the following uses of that basic_string object:<br />
— As an argument to non-member functions swap() (21.3.7.8), operator&gt;&gt;() (21.3.7.9), and getline() (21.3.7.9).<br />
— As an argument to basic_string::swap().<br />
<strong>— Calling data() and c_str() member functions.</strong><br />
— Calling non-const member functions, except operator[](), at(), begin(), rbegin(), end(), and rend().<br />
— Subsequent to any of the above uses except the forms of insert() and erase() which return iterators, the first call to non-const member functions operator[](), at(), begin(), rbegin(), end(), or rend().</p>
</blockquote>
</blockquote>
<p>Wenn ich das recht verstehe, sagt dieser Abschnitt ausdrücklich, daß folgendes zutrifft:</p>
<pre><code class="language-cpp">CharT&amp; c1 = theString[0]; // first call to non-const member function operator [] ()
theString[1]; // second call - c1 bleibt gültig!
CharT&amp; c2 = theString[0]; // da c1 fürderhin gültig bleibt, muß &amp;c1 == &amp;c2 sein
</code></pre>
<p>Zwar scheint die von dir hervorgehobene Stelle dagegen zu sprechen, weil der Rückgabewert von <code>operator [] ()</code> über <code>data()</code> definiert ist, doch mir scheint die explizite Erwähnung des Indexoperators in der Auflistung von höherem Gewicht zu sein, und die postuliert nur beim erstmaligen Aufruf eine Invalidierung vorheriger Referenzen.</p>
<p>Es ist richtig, daß die Bedingung <code>(&amp;(operator [] (n)) + 1 == &amp;(operator [] (n + 1))</code> nicht erfüllt sein muß, aber die von dir zitierte Stelle macht selbst meinen obigen Versuch, diesen Fall herbeizuführen, nichtig. Um also unter Erfüllung der zusätzlichen Forderung meine Annahme zu widerlegen, müßte <code>std::basic_string&lt;&gt;</code> für mit verschiedenen Indizes durchgeführte <code>operator [] ()</code> -Aufrufe Zeiger auf unterschiedliche Strings zurückgeben, dabei aber beim Aufruf mit demselben Index jedesmal dieselbe Referenz, und sobald z.B. <code>data()</code> aufgerufen wird, sämtliche Änderungen wieder zum tatsächlichen String zusammenführen. Und das ist, da sind wir uns sicherlich einig, dermaßen abstrus, daß man es getrost außer acht lassen kann <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Dravere schrieb:</p>
<blockquote>
<p>Im nächsten Standard wird dies glaub ich sogar korrigiert.</p>
</blockquote>
<p>Hoffentlich. Für <code>std::vector&lt;&gt;</code> korrigierte das ja, wenn ich mich recht erinnere, bereits der 2003er-Standard.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743819</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743819</guid><dc:creator><![CDATA[audacia]]></dc:creator><pubDate>Wed, 15 Jul 2009 21:38:32 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Wed, 15 Jul 2009 22:35:17 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/8276">@audacia</a>,<br />
Du verstehst mich wohl falsch oder ich dich. Ich wollte nur sagen, dass der zurückgelieferte Zeiger von <code>data</code> , nicht auf das interne Array verweisen muss. Daher kannst du über die linearen Daten, welche sich an der Adresse des von <code>data</code> zurückgelieferten Zeigers liegen, nicht darauf schliessen, dass sie intern auch linear angelegt sind. Es wäre möglich, dass sie im <code>basic_string</code> als Deque gespeichert sind.</p>
<pre><code class="language-cpp">template&lt;typename CharT, /* ... */ &gt;
class basic_string
{
  std::deque&lt;CharT&gt; m_characters;

  // ...

public:
  CharT const* data() const
  {
    static std::vector&lt;CharT&gt; buffer;
    buffer.resize(m_characters.size());
    std::copy(m_characters.begin(), m_characters.end(), buffer.begin());

    return &amp;buffer[0];
  }

  // ...

  CharT&amp; operator [](std::size_t index)
  {
    return m_characters[index]; // entspricht durchaus data()[index]
  }

  // ...
};

// Wenn du nun zum Beispiel sowas machst, dann hast du garantiertes undefiniertes Verhalten:
std::string mystring = &quot;test&quot;;
std::fill_n(&amp;mystring[0], 4, 0); // Fehlannahme, dass der Zeiger auf ein zusammenhängendes Array verweist.
</code></pre>
<p>Grüssli</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743840</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743840</guid><dc:creator><![CDATA[Dravere]]></dc:creator><pubDate>Wed, 15 Jul 2009 22:35:17 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Thu, 16 Jul 2009 08:31:26 GMT]]></title><description><![CDATA[<p>Dravere schrieb:</p>
<blockquote>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/8276">@audacia</a>,<br />
Du verstehst mich wohl falsch oder ich dich.</p>
</blockquote>
<p>Das befürchte ich.</p>
<p>Dravere schrieb:</p>
<blockquote>
<p>Ich wollte nur sagen, dass der zurückgelieferte Zeiger von <code>data</code> , nicht auf das interne Array verweisen muss. Daher kannst du über die linearen Daten, welche sich an der Adresse des von <code>data</code> zurückgelieferten Zeigers liegen, nicht darauf schliessen, dass sie intern auch linear angelegt sind. Es wäre möglich, dass sie im <code>basic_string</code> als Deque gespeichert sind.</p>
</blockquote>
<p>Das trifft zu, ist aber vollkommen irrelevant für meine obige Annahme.</p>
<p>Dravere schrieb:</p>
<blockquote>
<pre><code class="language-cpp">// Wenn du nun zum Beispiel sowas machst, dann hast du garantiertes undefiniertes Verhalten:
std::string mystring = &quot;test&quot;;
std::fill_n(&amp;mystring[0], 4, 0); // Fehlannahme, dass der Zeiger auf ein zusammenhängendes Array verweist.
</code></pre>
</blockquote>
<p>Nein, das ist keine Fehlannahme, denn dem Standard zufolge zeigt <code>data()</code> , über das der <code>operator [] ()</code> definiert ist, auf ein zusammenhängendes Array:</p>
<p>ISO/IEC 14882 schrieb:</p>
<blockquote>
<p><strong>21.3.6 basic_stringstring operations</strong><br />
<code>const charT* data() const;</code><br />
3 Returns: If size() is nonzero, the member returns a pointer to the initial element of an array whose first<br />
size() elements equal the corresponding elements of the string controlled by *this. If size() is<br />
zero, the member returns a non-null pointer that is copyable and can have zero added to it.</p>
</blockquote>
<p>Was der Standard nicht vorschreibt, ist, daß ich mittels <code>(&amp;operator [] (n))[1]</code> das Zeichen unter <code>operator [] (n + 1)</code> verändern kann. Aber hast du mal darüber nachgedacht, wie eine Implementation aussehen müßte, bei der das tatsächlich nicht der Fall ist? Falls nein, lies meinen obigen Post nocheinmal, da habe ich es ausgeführt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1743964</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1743964</guid><dc:creator><![CDATA[audacia]]></dc:creator><pubDate>Thu, 16 Jul 2009 08:31:26 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Thu, 16 Jul 2009 11:49:32 GMT]]></title><description><![CDATA[<p>audacia schrieb:</p>
<blockquote>
<p>Du beliebst maßlos zu übertreiben. Ich bemängele lediglich, daß sie stets als unumgänglich bessere Alternative dargestellt werden.</p>
</blockquote>
<p>Okay, das war etwas überspitzt formuliert. Mir ist jedoch aufgefallen, dass du die C++-Streams sehr oft schlecht machst - meiner Ansicht nach schlechter, als sie sind. Abgesehen davon ist die Aussage, Streams würden als unumgänglich bessere Alternative dargestellt, genauso übertrieben. Sie werden den Anfängern vielleicht als erste Möglichkeit vorgeschlagen, was auch seinen Grund hat. Etliche Fehlerquellen der C-Funktionen werden durch die Streams eingeschränkt oder ganz aus der Welt geschaffen, was einem Neuling sicher sehr entgegen kommt. Hingegen kann man als Anfänger die Nachteile der Streams eher leicht verkraften.</p>
<p>audacia schrieb:</p>
<blockquote>
<p>Was der Standard nicht vorschreibt, ist, daß ich mittels <code>(&amp;operator [] (n))[1]</code> das Zeichen unter <code>operator [] (n + 1)</code> verändern kann. Aber hast du mal darüber nachgedacht, wie eine Implementation aussehen müßte, bei der das tatsächlich nicht der Fall ist? Falls nein, lies meinen obigen Post nocheinmal, da habe ich es ausgeführt.</p>
</blockquote>
<p>Klar werden es vernünftige Implementierungen nicht so lösen - zum Beispiel würden diese für <code>c_str()</code> auch nicht ein neues Array mit '\0' erstellen.</p>
<p>Scheint schon so, als wäre diese Annahme in den meisten Fällen gewährleistet, darauf verlassen würde ich mich trotzdem nicht. Zum Beispiel muss <code>data()</code> auch keinen nullterminierten String zurückgeben. Oder kann Nullen innerhalb des Strings zurückgeben, die von den C-Funktionen als Terminierung angesehen werden.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1744107</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1744107</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Thu, 16 Jul 2009 11:49:32 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Thu, 16 Jul 2009 12:27:11 GMT]]></title><description><![CDATA[<p>audacia schrieb:</p>
<blockquote>
<p>Nein, das ist keine Fehlannahme, denn dem Standard zufolge zeigt <code>data()</code> , über das der <code>operator [] ()</code> definiert ist, auf ein zusammenhängendes Array:</p>
</blockquote>
<p>audacia schrieb:</p>
<blockquote>
<p>Was der Standard nicht vorschreibt, ist, daß ich mittels <code>(&amp;operator [] (n))[1]</code> das Zeichen unter <code>operator [] (n + 1)</code> verändern kann.</p>
</blockquote>
<p>Die beiden Sätze sind meiner Meinung nach der komplette Widerspruch. <code>operator [](index)</code> ist nur über <code>data()[index]</code> definiert, also dass hier der gleiche Wert zurückkommt. Es ist nicht definiert, dass der Zeiger auf das zurückgegebene Element gleich sein muss. Daher ist dies undefiniertes Verhalten:</p>
<pre><code class="language-cpp">std::fill_n(&amp;mystring[0], 4, 0);
</code></pre>
<p>Weil man hier eben davon ausgeht, dass man mittels <code>(&amp;operator [] (n))[1]</code> das Zeichen unter <code>operator [] (n + 1)</code> verändern kann. Was du selber sagst, dass es nicht vom Standard vorgeschrieben ist ...</p>
<p>audacia schrieb:</p>
<blockquote>
<p>Aber hast du mal darüber nachgedacht, wie eine Implementation aussehen müßte, bei der das tatsächlich nicht der Fall ist?</p>
</blockquote>
<p>Ja, ich bin sogar schon mal soweit gegangen, dass ich dies selber getestet habe. Es gibt durchaus eine gewisse Berechtigung für sowas. Wenn man nämlich Einfügeoperationen im <code>std::string</code> beschleunigen möchte, also nicht nur das Anfügen am Ende, dann kann man hier durch eine veränderte Speicherverwaltung eine gewisse Optimierung erzielen. Man kann zum Beispiel auch davon ausgehen, dass <code>c_str</code> und <code>data</code> Methoden sind, welche eher seltener aufgerufen werden und daher ruhig etwas teuerer sein dürfen.<br />
Also ganz so abwegig finde ich eine solche Implementation nicht.</p>
<p>Aber es ist wohl wie bei der Verwendung von variadischen Funktionen, wenn man das Risiko eingehen möchte, wobei man hier sogar nicht standardkonforme Operationen durchführt ... Du bist wohl einfach risikofreudiger als andere <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Grüssli</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1744156</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1744156</guid><dc:creator><![CDATA[Dravere]]></dc:creator><pubDate>Thu, 16 Jul 2009 12:27:11 GMT</pubDate></item><item><title><![CDATA[Reply to Code für Ausgabe vereinfachen. on Thu, 16 Jul 2009 14:33:17 GMT]]></title><description><![CDATA[<p>Dravere schrieb:</p>
<blockquote>
<p>Die beiden Sätze sind meiner Meinung nach der komplette Widerspruch. <code>operator [](index)</code> ist nur über <code>data()[index]</code> definiert, also dass hier der gleiche Wert zurückkommt.</p>
</blockquote>
<p><code>operator [] ()</code> gibt eine Referenz zurück, über die du den Wert ändern kannst. Das macht den Unterschied aus.</p>
<p>Dravere schrieb:</p>
<blockquote>
<p>audacia schrieb:</p>
<blockquote>
<p>Aber hast du mal darüber nachgedacht, wie eine Implementation aussehen müßte, bei der das tatsächlich nicht der Fall ist?</p>
</blockquote>
<p>Ja, ich bin sogar schon mal soweit gegangen, dass ich dies selber getestet habe. Es gibt durchaus eine gewisse Berechtigung für sowas. Wenn man nämlich Einfügeoperationen im <code>std::string</code> beschleunigen möchte, also nicht nur das Anfügen am Ende, dann kann man hier durch eine veränderte Speicherverwaltung eine gewisse Optimierung erzielen. Man kann zum Beispiel auch davon ausgehen, dass <code>c_str</code> und <code>data</code> Methoden sind, welche eher seltener aufgerufen werden und daher ruhig etwas teuerer sein dürfen.<br />
Also ganz so abwegig finde ich eine solche Implementation nicht.</p>
</blockquote>
<p>Na, dann zeig mal her. Davon ausgehend, daß die Motivation für deine Implementation &quot;nicht ganz abwegig&quot; ist, behaupte ich: entweder ist deine Implementation nicht standardkonform, oder meine obige Annahme trifft zu.</p>
<p>Dravere schrieb:</p>
<blockquote>
<p>Aber es ist wohl wie bei der Verwendung von variadischen Funktionen, wenn man das Risiko eingehen möchte</p>
</blockquote>
<p>Keine Sorge, bei mir sind <code>printf()</code> und dergleichen allesamt typsicher <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1744318</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1744318</guid><dc:creator><![CDATA[audacia]]></dc:creator><pubDate>Thu, 16 Jul 2009 14:33:17 GMT</pubDate></item></channel></rss>