<?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[Irgendwie generische Schnittstelle, oder auch nicht.]]></title><description><![CDATA[<p>Ich hatte jetzt schon öfter die Situation, dass ich eine Funktion hatte, die in C in etwa so ausgesehen hätte:</p>
<pre><code class="language-cpp">void do_smth_with_me(type_t *p, size_t s)
  ...
</code></pre>
<p>Also eine klare Situation: Hier soll über ein Array iteriert werden. Jetzt die Frage, wie macht man das in C++? Genau so? Das wäre aber doof, da inkompatibel mit vielen Standard-Containern. Aber macht eine generische Schnittstelle mit Iteratoren Sinn? Denn im Endeffekt sollen die Iteratoren zwar egal sein, aber die Dereferenzierung muss ja ein bestimmter Typ sein. Also ist die Funktion irgendwie doch kein &quot;richtiger&quot; Template-Kandidat. Wie macht ihr das?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/292281/irgendwie-generische-schnittstelle-oder-auch-nicht</link><generator>RSS for Node</generator><lastBuildDate>Mon, 17 Aug 2026 02:58:14 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/292281.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 06 Sep 2011 12:31:33 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 12:31:33 GMT]]></title><description><![CDATA[<p>Ich hatte jetzt schon öfter die Situation, dass ich eine Funktion hatte, die in C in etwa so ausgesehen hätte:</p>
<pre><code class="language-cpp">void do_smth_with_me(type_t *p, size_t s)
  ...
</code></pre>
<p>Also eine klare Situation: Hier soll über ein Array iteriert werden. Jetzt die Frage, wie macht man das in C++? Genau so? Das wäre aber doof, da inkompatibel mit vielen Standard-Containern. Aber macht eine generische Schnittstelle mit Iteratoren Sinn? Denn im Endeffekt sollen die Iteratoren zwar egal sein, aber die Dereferenzierung muss ja ein bestimmter Typ sein. Also ist die Funktion irgendwie doch kein &quot;richtiger&quot; Template-Kandidat. Wie macht ihr das?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2115695</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115695</guid><dc:creator><![CDATA[vll]]></dc:creator><pubDate>Tue, 06 Sep 2011 12:31:33 GMT</pubDate></item><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 12:39:32 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">template &lt;class InputIterator&gt; void foo ( InputIterator first, InputIterator last);
</code></pre>
<p>Deine Einwände gegen Iteratoren und Templates verstehe ich nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2115699</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115699</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Tue, 06 Sep 2011 12:39:32 GMT</pubDate></item><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 12:56:19 GMT]]></title><description><![CDATA[<p>SeppJ schrieb:</p>
<blockquote>
<p>Deine Einwände gegen Iteratoren und Templates verstehe ich nicht.</p>
</blockquote>
<pre><code class="language-cpp">struct Good
{
  void FooBar()
  {
    std::cout &lt;&lt; &quot;Hallo!\n&quot;;
  }
};

struct Bad
{
  void FooBar()
  {
    std::cout &lt;&lt; &quot;Fail!\n&quot;;
  }
};

template&lt;class InputIterator&gt;
void foo(InputIterator first, InputIterator last)
{ // Ist nur für Good gedacht.
  for (; first != last; ++first);
    first-&gt;FooBar();
}

int main()
{
  std::vector&lt;Bad&gt; v(10);
  foo(v.begin(), v.end()); // Fail. Und es gibt nicht mal einen Compiler-Fehler.
}
</code></pre>
<p>Oder übersehe ich da was?<br />
Und auch wenn man bei diesem Beispiel schon Pech haben muss, mein Problem mit dieser Methode ist einfach, dass man der Funktion quasi jeden &quot;Mist&quot; übergeben kann, wäre es nicht schöner, wenn man irgendwie von außen zeigen könnte, dass sie nur für eine bestimmte Klasse ist?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2115709</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115709</guid><dc:creator><![CDATA[vll]]></dc:creator><pubDate>Tue, 06 Sep 2011 12:56:19 GMT</pubDate></item><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 12:58:05 GMT]]></title><description><![CDATA[<p>vll schrieb:</p>
<blockquote>
<p>[...] aber die Dereferenzierung muss ja ein bestimmter Typ sein.</p>
</blockquote>
<p>Ist ja nicht schlimm. Das wäre eine Sache für die Dokumentation. Da sagst Du dann, &quot;Iteratoren für eine type_t-Sequenz&quot; oder so. Wenn man das Funktionstemplate dann anders benutzen wollen würde, gibt es eben einen Fehler zur Cmopile-Zeit (duck typing zur compile zeit).</p>
<p>Wenn Du das Funktionstemplate allerdings schon vor der Überladungsauflösung wegschmneißen willst, wenn eine bestimmte Bedingung nicht erfüllt ist (constraining), dann könntest Du das per enable_if machen:</p>
<pre><code>[b]template&lt;class Iter&gt;[/b]
typename boost::enable_if&lt;
  boost::is_same&lt; typename iterator_traits&lt;Iter&gt;::value_type, type_t &gt;
,[b]void[/b]&gt;::type [b]do_smthing(Iter beg, Iter end)
{
  ___
}[/b]
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2115711</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115711</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Tue, 06 Sep 2011 12:58:05 GMT</pubDate></item><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 13:08:11 GMT]]></title><description><![CDATA[<p>vll schrieb:</p>
<blockquote>
<pre><code class="language-cpp">[...]
int main()
{
  std::vector&lt;Bad&gt; v(10);
  foo(v.begin(), v.end()); // Fail. Und es gibt nicht mal einen Compiler-Fehler.
}
</code></pre>
<p>Oder übersehe ich da was?</p>
</blockquote>
<p>Was soll denn sonst passieren? Was gibt es denn besseres als einen Fehler zur Compile-Zeit?</p>
<p>vll schrieb:</p>
<blockquote>
<p>Und auch wenn man bei diesem Beispiel schon Pech haben muss, mein Problem mit dieser Methode ist einfach, dass man der Funktion quasi jeden &quot;Mist&quot; übergeben kann,</p>
</blockquote>
<p>Geht ja nicht. Hast Du selbst gezeigt.</p>
<p>vll schrieb:</p>
<blockquote>
<p>wäre es nicht schöner, wenn man irgendwie von außen zeigen könnte, dass sie nur für eine bestimmte Klasse ist?</p>
</blockquote>
<p>Dafür ist Dokumentation gut. In Form von selbstdokumentierenden C++ Code lässt sich das noch nicht ausdrücken -- es sei denn, du zählst das &quot;SFINAE&quot; constraining dazu (siehe mein vorheriges Beispiel). Aber so leserlich ist das nicht wirklich. Man kann es aber dazu verwenden, Compiler-Fehlermeldungen zu kürzen und Überladungs-Mehrdeutigkeiten zu entfernen.</p>
<p>Du bist aber nicht der einzige, der diese Bedingungen &quot;nativ&quot; ausdrücken können möchte. Beispiel:</p>
<pre><code>template&lt;[b]InputIterator[/b] Iter&gt;
[b]requires SameType&lt;Iter::value_type,type_t&gt;[/b]
void do_smthing(Iter beg, Iter end)
{
___
}
</code></pre>
<p>So eine Spracherweiterung ist aber noch nicht 100% zu Ende gedacht. Vielleicht kommt das irgendwann nochmal beim nächsten Sprachstandard.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2115715</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115715</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Tue, 06 Sep 2011 13:08:11 GMT</pubDate></item><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 13:06:08 GMT]]></title><description><![CDATA[<p>krümelkacker schrieb:</p>
<blockquote>
<p>Was soll denn sonst passieren? Was gibt es denn besseres als einen Fehler zur Compile-Zeit?</p>
</blockquote>
<p>Einen Fehler vor der Template-Auflösung. Aber ich glaube, dir ist nicht bewusst, dass das Beispiel oben anstandslos kompiliert? <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/2115719</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115719</guid><dc:creator><![CDATA[vll]]></dc:creator><pubDate>Tue, 06 Sep 2011 13:06:08 GMT</pubDate></item><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 13:10:49 GMT]]></title><description><![CDATA[<p>vll schrieb:</p>
<blockquote>
<p>krümelkacker schrieb:</p>
<blockquote>
<p>Was soll denn sonst passieren? Was gibt es denn besseres als einen Fehler zur Compile-Zeit?</p>
</blockquote>
<p>Einen Fehler vor der Template-Auflösung. Aber ich glaube, dir ist nicht bewusst, dass das Beispiel oben anstandslos kompiliert? <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>
</blockquote>
<p>Richtig. Ich habe es nur überflogen und Deinen &quot;Fail&quot;-Kommentar als Compile-Zeit-Fehler interpretiert. Nächste Frage: Ist es schlimm, dass es kompiliert?</p>
<p>Wie gesagt: Constraining geht -- aber eben mit Tricks statt direkter Sprachunterstützung.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2115721</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115721</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Tue, 06 Sep 2011 13:10:49 GMT</pubDate></item><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 13:09:33 GMT]]></title><description><![CDATA[<p>Entweder einfach davon ausgehen, dass der Iterator-value_type zu dem passt, was du machen willst. Da könnten dann natürlich nicht nur Iteratoren auf type_t funktionieren, sondern auch auf something_like_type_t, wenn der die nötige Schnittstelle anbietet. Das wäre dann ein Fall von statischer Polymorphie.</p>
<pre><code class="language-cpp">struct type_t
{
  void smth()
  {
    std::cout &lt;&lt; &quot;I am a type_t\n&quot;;
  }
};

struct something_like_type_t
{
  int smth() const
  {
    std::cout &lt;&lt; &quot;No type_t, but can do smth, too\n&quot;;
    return 1;
  }
};

template &lt;class Iterator&gt;
void do_smth_with_me(Iterator first, Iterator last)
{
  while (first != last)
    (first++)-&gt;smth();
}

int main()
{
  std::vector&lt;type_t&gt; real(3);
  std::deque&lt;something_like_type_t&gt; fake(2);

  do_smth_with_me(real.begin(), real.end());
  do_smth_with_me(fake.rbegin(), fake.rend());
}
</code></pre>
<p>Alternativ, wenn du wirklich nur type_t als value_type zulassen willst, kannst du das je nach C++-Version absichern:</p>
<pre><code class="language-cpp">#include &lt;iterator&gt;
#if defined(HAS_0X_TYPE_TRAITS)
  #include &lt;type_traits&gt; //C++0x
  using std::is_same; //C++0x
#elif defined(HAS_TR1_TYPE_TRAITS)
  #include &lt;type_traits&gt; //TR1
  using std::tr1::is_same; //TR1
#endif

#ifdef HAS_NO_0X_STATIC_ASSERT
  #include &lt;boost/static_assert.hpp&gt; //boost
#endif

void do_smth_with_me(Iterator first, Iterator last)
{
  const static bool is_type_t = is_same&lt;type_t,std::iterator_traits&lt;Iterator&gt;::value_type&gt;::value;
  static_assert(is_type_t, &quot;must be type_t&quot;); //C++0x
  BOOST_STATIC_ASSERT_MSG(is_type_t, &quot;must be type_t&quot;); //boost
  while (first != last)
    (first++)-&gt;smth();
}
</code></pre>
<p>Die HAS_xy-Makros hab ich frei erfunden, es gibt aber z.B. in Boost.Configuration ähnliches.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2115722</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115722</guid><dc:creator><![CDATA[pumuckl]]></dc:creator><pubDate>Tue, 06 Sep 2011 13:09:33 GMT</pubDate></item><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 13:11:15 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">inline void check_good(const Good &amp;)
{
}

template&lt;class InputIterator&gt; 
void foo(InputIterator first, InputIterator last) 
{ // Ist nur für Good gedacht. 
  for (; first != last; ++first); 
  {
    check_good(*first);
    first-&gt;FooBar(); 
  }
} 

int main() 
{ 
  std::vector&lt;Bad&gt; v(10); 
  foo(v.begin(), v.end()); //Compile-Fehler ohne Boost und Template-Gebastel
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2115723</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115723</guid><dc:creator><![CDATA[TyRoXx]]></dc:creator><pubDate>Tue, 06 Sep 2011 13:11:15 GMT</pubDate></item><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 13:16:39 GMT]]></title><description><![CDATA[<p>Mir ist noch etwas eingefallen. Es gibt auch &quot;polymorphe&quot; Iteratoren. Das, was da per type-eraures versteckt wird, ist der Container-Typ, nicht aber der Element-Typ.</p>
<pre><code class="language-cpp">void do_something(any_input_iter&lt;const type_t&gt; begin, any_input_iter&lt;const type_t&gt; end);
</code></pre>
<p>wobei dann &quot;any_inut_iter&quot; ein Klassen-Template ist, was den tatsächlichen Iterator-Typ versteckt. Für Iteratoren ist das aber recht unpopulär. Bei Funktionsobjekten sieht das schon anders aus:</p>
<pre><code class="language-cpp">void function_sink(boost::function&lt;double(double,double)&gt; func)
{
  double x = func(2.7,3.1);
  ...
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2115725</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115725</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Tue, 06 Sep 2011 13:16:39 GMT</pubDate></item><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 13:24:23 GMT]]></title><description><![CDATA[<p>TyroXx hat mich auf eine Idee gebracht:</p>
<pre><code class="language-cpp">template&lt;class InputIterator&gt;
void foo(InputIterator first, InputIterator last)
{ // Ist nur für Good gedacht.
  for (; first != last; ++first);
    Good(*first).FooBar();
}
</code></pre>
<p>Die Fehlermeldung ist auch gut:</p>
<blockquote>
<p>cannot convert from 'Bad' to 'Good'</p>
</blockquote>
<p>Edit:<br />
Wobei man Annahmen über den Konstruktor machen muss..</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2115727</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115727</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Tue, 06 Sep 2011 13:24:23 GMT</pubDate></item><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 13:53:03 GMT]]></title><description><![CDATA[<p>Solche Templates benutze ich in normalen Projekten (also keine headeronly Bibliothek o.ä) sowieso fast nur als kleine Helfer, die eigentlich nichts machen, als die für jedes Element die eigentliche Methode aufzurufen, die dann in der cpp definiert ist (oder einen insert in einen STL Container o.ä.). Die eigentliche Implementierung sollte i.d.R. nicht in irgendwelchen öffentlichen Headern herumschwirren. Damit hat sich das &quot;Problem&quot; auch ergeben, dass man irgendeinen Müll übergeben kann (ich find dieses Tatsache auch nicht so wahnsinnig problematisch).</p>
<p>Dein Beispiel:</p>
<pre><code class="language-cpp">struct Good
{
  void FooBar()
  {
    std::cout &lt;&lt; &quot;Hallo!\n&quot;;
  }
};

struct Bad
{
  void FooBar()
  {
    std::cout &lt;&lt; &quot;Fail!\n&quot;;
  }
};

// myclass.hpp
class MyClass
{
public:
  template&lt;class InputIterator&gt;
  void foo(InputIterator first, InputIterator last)
  { // Ist nur für Good gedacht.
    for (; first != last; ++first);
      foo(*first);  // geht nur mit Good
  }
  template&lt;class InputIterator&gt;
  void add(InputIterator first, InputIterator last)
  { // Ist nur für Good gedacht.
    myGoods.insert(myGoods.end(), first, last);  // geht nur mit Good
  }
private:
  void foo(Good&amp;);
  std::vector&lt;Good&gt; myGoods;
};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2115748</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115748</guid><dc:creator><![CDATA[brotbernd]]></dc:creator><pubDate>Tue, 06 Sep 2011 13:53:03 GMT</pubDate></item><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 14:07:34 GMT]]></title><description><![CDATA[<p>Je nachdem, was du da machen willst, solltest du noch das Semikolon hinter der for-Schleife entfernen:</p>
<pre><code class="language-cpp">template&lt;class InputIterator&gt;
  void foo(InputIterator first, InputIterator last)
  { // Ist nur für Good gedacht.
    for (; first != last; ++first);  // &lt;-- hier!
      foo(*first);  // geht nur mit Good
  }
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2115757</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115757</guid><dc:creator><![CDATA[nochnGast]]></dc:creator><pubDate>Tue, 06 Sep 2011 14:07:34 GMT</pubDate></item><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 14:09:29 GMT]]></title><description><![CDATA[<p>pumuckl schrieb:</p>
<blockquote>
<p>... Das wäre dann ein Fall von statischer Polymorphie.</p>
<pre><code class="language-cpp">struct type_t
{
  void smth()
  {
    std::cout &lt;&lt; &quot;I am a type_t\n&quot;;
  }
};

struct something_like_type_t
{
  int smth() const
  {
    std::cout &lt;&lt; &quot;No type_t, but can do smth, too\n&quot;;
    return 1;
  }
};

template &lt;class Iterator&gt;
void do_smth_with_me(Iterator first, Iterator last)
{
  while (first != last)
    (first++)-&gt;smth();
}

int main()
{
  std::vector&lt;type_t&gt; real(3);
  std::deque&lt;something_like_type_t&gt; fake(2);

  do_smth_with_me(real.begin(), real.end());
  do_smth_with_me(fake.rbegin(), fake.rend());
}
</code></pre>
</blockquote>
<p>(Info: bin noch nicht so lange mit C++ zu gange, komme aus der C#-Welt)<br />
Ist das überhaupt ein guter Programmier-Stil? Auf den ersten Blick sah das für mich nach <a href="http://de.wikipedia.org/wiki/Duck-Typing" rel="nofollow">Duck Typing</a> aus und statische-polymorphie war vorher für mich noch nicht einmal ein begriff.<br />
Also, meine eigentliche frage: Gilt sowas überhaupt als Schnittstelle? eigentlich ist das doch nur ein Compiler-Feature, welches bei nicht 100% Know-How nur zu solch unnötig komplizierten Fehlern/Fragen kommt?!<br />
Meiner Meinung nach (lasse mich natürlich übereden!) ist die Verwendung durch dynamische Polymorphie (sprich, die Verwendung von &quot;richtigen&quot; Schnittstellen) die bessere Variante, oder nich?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2115759</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115759</guid><dc:creator><![CDATA[pohlmann90]]></dc:creator><pubDate>Tue, 06 Sep 2011 14:09:29 GMT</pubDate></item><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 15:56:57 GMT]]></title><description><![CDATA[<p>krümelkacker schrieb:</p>
<blockquote>
<p>Mir ist noch etwas eingefallen. Es gibt auch &quot;polymorphe&quot; Iteratoren. Das, was da per type-eraures versteckt wird, ist der Container-Typ, nicht aber der Element-Typ.</p>
<pre><code class="language-cpp">void do_something(any_input_iter&lt;const type_t&gt; begin, any_input_iter&lt;const type_t&gt; end);
</code></pre>
<p>(...)</p>
</blockquote>
<p>Was mich dabei stört, ist, dass die Performance gröber darunter leidet.<br />
Iteratoren werden überall als &quot;cheap to copy&quot; verwendet, da normale Iteratoren eben auch billig zu kopieren sind.</p>
<p>Bloss polymorphe Iteratoren sind nicht billig zu kopieren. Zumindest dann nicht, wenn sie keine &quot;Small Object Optimization&quot; ala boost::function enthalten, und die ist leider gar nicht trivial korrekt zu implementieren.</p>
<p>Ich hab' daher in meinen Projekten bisher immer abstrakte &quot;Enumeratoren&quot; verwendet:</p>
<pre><code class="language-cpp">template &lt;class T&gt;
class AbstractEnumerator
{
public:
    virtual void Reset() = 0;
    virtual void MoveNext() = 0;

    virtual bool HasCurrent() const = 0;
    virtual T&amp; GetCurrent() const = 0;
};

template &lt;class T, class I&gt;
class IteratorPairEnumerator
{
    // ...
};

void do_something(AbstractEnumerator&lt;const type_t&gt;&amp; enumerator);
</code></pre>
<p>Das ist jetzt nicht so &quot;C++ig&quot;, aber ist einfach umzusetzen und funktioniert.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2115795</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115795</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 06 Sep 2011 15:56:57 GMT</pubDate></item><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 17:53:28 GMT]]></title><description><![CDATA[<p>Sicher, man kann nicht alles haben. Ich bin da jetzt auch kein Fan von solchen Iteratoren. Spätestens der Vergleich current!=end wird ekelig, wenn man erstmal per typeid testen muss, ob die überhaupt kompatibel sind. Da ist die Abstraktion &quot;C++ Iterator&quot; nicht die beste.</p>
<p>Wenn ich mich richtig erinnere, müsste ich mal zum Spaß eine &quot;any_range&quot; nach dem range-Konzept von Alexandrescu geschrieben haben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2115836</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115836</guid><dc:creator><![CDATA[krümelk_im_cafe]]></dc:creator><pubDate>Tue, 06 Sep 2011 17:53:28 GMT</pubDate></item><item><title><![CDATA[Reply to Irgendwie generische Schnittstelle, oder auch nicht. on Tue, 06 Sep 2011 18:33:23 GMT]]></title><description><![CDATA[<p>krümelk_im_cafe schrieb:</p>
<blockquote>
<p>Sicher, man kann nicht alles haben. Ich bin da jetzt auch kein Fan von solchen Iteratoren. Spätestens der Vergleich current!=end wird ekelig, wenn man erstmal per typeid testen muss, ob die überhaupt kompatibel sind.</p>
</blockquote>
<p>Wieso, der type_info Vergleich ist ja kein Problem.</p>
<p>Ich gehe davon aus, dass alle vernünftigen Compiler erstmal checken ob die Adresse der beiden type_info Instanzen gleich ist, &quot;succeed fast&quot; sozusagen. Und dann erst anfangen die Namens-Strings oder was auch immer zu vergleichen.</p>
<p>Falls man wirklich ein System hat wo der Vergleich zu lange dauert, kann man den &quot;succees fast&quot; Teil selbst basteln: Type-ID-Helper-Template das ne statische Variable hält, die Adresse dieser verwendet man als &quot;fast typeid&quot;. Normalerweise würde das schon ausreichen, aber da man vermutlich auch Systeme unterstützen will die sowas wie DLLs kennen, macht man im &quot;Adressen ungleich&quot; Fall noch einen zusätzlichen Test über typeid().</p>
<p>Da der &quot;Adressen gleich&quot; Fall der interessante ist (weil genau der am häufigsten vorkommen wird), sollte das reichen.</p>
<p>Ganz abgesehen davon dass es AFAIK sowieso UB ist zwei Iteratoren zu vergleichen die nicht vom selben Container kommen. D.h. man müsste diese Tests nur in Debug-Builds machen - Release-Builds lässt man einfach schön in UB reinlaufen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2115849</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2115849</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Tue, 06 Sep 2011 18:33:23 GMT</pubDate></item></channel></rss>