<?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[Vermeidung mehrdeutiger Templates]]></title><description><![CDATA[<p>Ich wollte eine Templatefunktion schreiben, die mit boost::range beliebige Container ausgeben kann (sind meine ersten Spielereinen mit boost::range). Meine erste naive Idee sah so aus:</p>
<pre><code class="language-cpp">template&lt;class Container&gt;
ostream&amp; operator &lt;&lt; (ostream&amp; o, const Container&amp; c)
{
	typedef typename boost::range_const_iterator&lt;Container&gt;::type iterator;

	for(iterator i = boost::begin(c), end = boost::end(c); i != end; ++i)
		o &lt;&lt; *i &lt;&lt; &quot;, &quot;;
}
</code></pre>
<p>Allerdings liefert das Probleme, wenn schon ein überladener op&lt;&lt; existiert, z.B. bei std::string (mehrdeutiger Aufruf). Wenn ich mit boost::enable_if und is_same gespielt und string ausgeschlossen habe, war das nächste Problem bei std::char_traits. Außerdem denk ich, ist es der falsche Weg, explizit alle problematischen Typen auszuschließen.<br />
Ich suche also eine möglichst einfache Möglichkeit, per enable_if oder wie auch immer die Typen auszuschließen, bei denen schon ein op&lt;&lt; existiert.<br />
Kennt jemand eine gute Lösung für mein Problem?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/267815/vermeidung-mehrdeutiger-templates</link><generator>RSS for Node</generator><lastBuildDate>Wed, 02 Sep 2026 07:10:58 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/267815.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 30 May 2010 20:28:06 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Vermeidung mehrdeutiger Templates on Sun, 30 May 2010 20:28:06 GMT]]></title><description><![CDATA[<p>Ich wollte eine Templatefunktion schreiben, die mit boost::range beliebige Container ausgeben kann (sind meine ersten Spielereinen mit boost::range). Meine erste naive Idee sah so aus:</p>
<pre><code class="language-cpp">template&lt;class Container&gt;
ostream&amp; operator &lt;&lt; (ostream&amp; o, const Container&amp; c)
{
	typedef typename boost::range_const_iterator&lt;Container&gt;::type iterator;

	for(iterator i = boost::begin(c), end = boost::end(c); i != end; ++i)
		o &lt;&lt; *i &lt;&lt; &quot;, &quot;;
}
</code></pre>
<p>Allerdings liefert das Probleme, wenn schon ein überladener op&lt;&lt; existiert, z.B. bei std::string (mehrdeutiger Aufruf). Wenn ich mit boost::enable_if und is_same gespielt und string ausgeschlossen habe, war das nächste Problem bei std::char_traits. Außerdem denk ich, ist es der falsche Weg, explizit alle problematischen Typen auszuschließen.<br />
Ich suche also eine möglichst einfache Möglichkeit, per enable_if oder wie auch immer die Typen auszuschließen, bei denen schon ein op&lt;&lt; existiert.<br />
Kennt jemand eine gute Lösung für mein Problem?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1904679</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1904679</guid><dc:creator><![CDATA[ipsec]]></dc:creator><pubDate>Sun, 30 May 2010 20:28:06 GMT</pubDate></item><item><title><![CDATA[Reply to Vermeidung mehrdeutiger Templates on Mon, 31 May 2010 08:09:11 GMT]]></title><description><![CDATA[<p>In deinem Fall würde ich mir einfach zunutze machen, dass boost::iterator_range bereits eine Konvertierung von Containern erlaubt und statt eines Containers dem op&lt;&lt; einfach eine Range als zweiten Parameter geben.<br />
Bei std::string gibt es dann schon eine direkte Überladung von op&lt;&lt;, und die implizite Konvertierung in eine iterator_range wird nicht in Betracht gezogen.</p>
<pre><code class="language-cpp">#include &lt;boost/range/iterator_range.hpp&gt;
#include &lt;vector&gt;
#include &lt;iostream&gt;

template &lt;class ForwardTraversalIterator&gt;
std::ostream&amp; operator&lt;&lt; (std::ostream&amp; os, boost::iterator_range&lt;ForwardTraversalIterator&gt; const&amp; range)
{
  typedef typename boost::iterator_range&lt;ForwardTraversalIterator&gt;::iterator iter_t;
  iter_t it = range.begin();
  os &lt;&lt; '[' &lt;&lt; *(it++);
  for (iter_t end = range.end(); it != end; ++it)
  {
    os &lt;&lt; ',' &lt;&lt; *it;
  }
  os &lt;&lt; ']';
  return os;
}

int main()
{
  std::vector&lt;int&gt; ivec;
  for(int i = 1; i &lt; 200; i *= 2)
  {
    ivec.push_back(i);
  }

  std::cout &lt;&lt; ivec &lt;&lt; std::endl;
}
</code></pre>
<p><a href="http://codepad.org/oCs8IeGm" rel="nofollow">Getestet auf codepad.org</a></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1904771</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1904771</guid><dc:creator><![CDATA[pumuckl]]></dc:creator><pubDate>Mon, 31 May 2010 08:09:11 GMT</pubDate></item><item><title><![CDATA[Reply to Vermeidung mehrdeutiger Templates on Mon, 31 May 2010 08:54:37 GMT]]></title><description><![CDATA[<p>pumuckl schrieb:</p>
<blockquote>
<p>Bei std::string gibt es dann schon eine direkte Überladung von op&lt;&lt;, und die implizite Konvertierung in eine iterator_range wird nicht in Betracht gezogen.</p>
</blockquote>
<p>Die wird in keinem Fall in Betracht gezogen, wenn das Argument für die Deduktion des Templatearguments herangezogen wird.</p>
<p><a href="http://codepad.org/oCs8IeGm" rel="nofollow">Getestet auf codepad.org</a>Trotzdem kein Standard C++.</p>
<p>Eine simple Lösung wäre das Funktionstemplate <em>allgemeiner</em> zu gestalten als die speziellen Überladungen z.B. für std::string.</p>
<pre><code class="language-cpp">template&lt;class charT, class traits, class Allocator&gt;
basic_ostream&lt;charT, traits&gt;&amp; operator&lt;&lt;(basic_ostream&lt;charT, traits&gt;&amp; os, const basic_string&lt;charT,traits,Allocator&gt;&amp; str);
</code></pre>
<p>ist die Überladung für std::string.</p>
<pre><code class="language-cpp">template&lt;class Container&gt;
ostream&amp; operator &lt;&lt; (ostream&amp; o, const Container&amp; c)
</code></pre>
<p>ist diesbezüglich ungeordnet.</p>
<p>Mit</p>
<pre><code class="language-cpp">template&lt;class charT, class traits, class Container&gt;
basic_ostream&lt;charT,traits&gt;&amp; operator &lt;&lt; (basic_ostream&lt;charT,traits&gt;&amp; o, const Container&amp; c)
</code></pre>
<p>besteht hingegen kein Problem, da die Überladung für std::string spezieller ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1904794</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1904794</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Mon, 31 May 2010 08:54:37 GMT</pubDate></item><item><title><![CDATA[Reply to Vermeidung mehrdeutiger Templates on Mon, 31 May 2010 08:58:42 GMT]]></title><description><![CDATA[<p>camper schrieb:</p>
<blockquote>
<p><a href="http://codepad.org/oCs8IeGm" rel="nofollow">Getestet auf codepad.org</a>Trotzdem kein Standard C++.</p>
</blockquote>
<p>Weils boost benutzt oder noch aus einem anderen Grund?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1904796</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1904796</guid><dc:creator><![CDATA[pumuckl]]></dc:creator><pubDate>Mon, 31 May 2010 08:58:42 GMT</pubDate></item><item><title><![CDATA[Reply to Vermeidung mehrdeutiger Templates on Mon, 31 May 2010 09:10:05 GMT]]></title><description><![CDATA[<p>pumuckl schrieb:</p>
<blockquote>
<p>camper schrieb:</p>
<blockquote>
<p><a href="http://codepad.org/oCs8IeGm" rel="nofollow">Getestet auf codepad.org</a>Trotzdem kein Standard C++.</p>
</blockquote>
<p>Weils boost benutzt oder noch aus einem anderen Grund?</p>
</blockquote>
<p>Weil, wie ich oben schon sagte, in</p>
<pre><code class="language-cpp">std::cout &lt;&lt; ivec
</code></pre>
<p>eine Konvertierung in</p>
<pre><code class="language-cpp">boost::iterator_range&lt;ForwardTraversalIterator&gt;
</code></pre>
<p>in ausgeschlossen ist, weil ivec selbst zur Deduktion des Templateparameters benutzt wird (und diese Deduktion ebenso fehlschlagen muss).</p>
<p>gcc 4.4.3 schrieb:</p>
<blockquote>
<p>test.cpp: In function ‘int main()’:<br />
test.cpp:27: error: no match for ‘operator&lt;&lt;’ in ‘std::cout &lt;&lt; ivec’<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/ostream:108: note: candidates are: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(std::basic_ostream&lt;_CharT, _Traits&gt;&amp; (<em>)(std::basic_ostream&lt;_CharT, _Traits&gt;&amp;)) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/ostream:117: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(std::basic_ios&lt;_CharT, _Traits&gt;&amp; (</em>)(std::basic_ios&lt;_CharT, _Traits&gt;&amp;)) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/ostream:127: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(std::ios_base&amp; (<em>)(std::ios_base&amp;)) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/ostream:165: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(long int) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/ostream:169: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(long unsigned int) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/ostream:173: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(bool) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/bits/ostream.tcc:91: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(short int) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/ostream:180: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(short unsigned int) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/bits/ostream.tcc:105: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(int) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/ostream:191: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(unsigned int) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/ostream:200: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(long long int) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/ostream:204: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(long long unsigned int) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/ostream:209: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(double) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/ostream:213: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(float) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/ostream:221: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(long double) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/ostream:225: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(const void</em>) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]<br />
/usr/lib/gcc/x86_64-pc-linux-gnu/4.4.3/include/g++-v4/bits/ostream.tcc:119: note: std::basic_ostream&lt;_CharT, _Traits&gt;&amp; std::basic_ostream&lt;_CharT, _Traits&gt;::operator&lt;&lt;(std::basic_streambuf&lt;_CharT, _Traits&gt;*) [with _CharT = char, _Traits = std::char_traits&lt;char&gt;]</p>
</blockquote>
<p>es wird also kein passender Kandidat gefunden, wie zu erwarten ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1904798</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1904798</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Mon, 31 May 2010 09:10:05 GMT</pubDate></item><item><title><![CDATA[Reply to Vermeidung mehrdeutiger Templates on Mon, 31 May 2010 10:17:23 GMT]]></title><description><![CDATA[<p>Ok vielen Dank für die Antworten.<br />
pumuckls Lösung funktioniert wie angedeutet leider nicht, compers Variante mit der allgemeineren Signatur schon.<br />
Die Funktion sieht jetzt so aus:</p>
<pre><code class="language-cpp">template&lt;class charT, class traits, class  Container&gt;
basic_ostream&lt;charT,traits&gt;&amp; operator &lt;&lt; (basic_ostream&lt;charT,traits&gt;&amp; o, const Container&amp; c)
{
	typedef typename boost::range_const_iterator&lt;Container&gt;::type iterator;

	iterator i = boost::begin(c), end = boost::end(c);
	o &lt;&lt; '[' &lt;&lt; *(i++);
	for(; i != end; ++i)
		o &lt;&lt; &quot;, &quot; &lt;&lt; *i;
	o &lt;&lt; ']';

	return o;
}
</code></pre>
<p>Und funktioniert wie gewünscht (ich meine sogar, verstanden zu haben, wieso).<br />
Man lernt eben echt nie aus in C++ <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/1904828</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1904828</guid><dc:creator><![CDATA[ipsec]]></dc:creator><pubDate>Mon, 31 May 2010 10:17:23 GMT</pubDate></item></channel></rss>