<?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[c# IEnumerator in c++]]></title><description><![CDATA[<p>Hallo Leute,</p>
<p>ich versuche so eine Art CLR IEnumerator in C++ abzubilden. Ich werde mit<br />
templates und traits so langsam besser, aber so ganz reichts wohl noch nicht.<br />
Das IEnumerator Interface sieht in C# in etwa so aus:</p>
<pre><code>public interface IEnumerator&lt;T&gt;
{
    // Returns true, if MoveNext() succeeds and Current is a valid T
    bool MoveNext();
    // a valid T if the previous MoveNext() succeeds
    T Current { get; }
    // Returns to Initial state
    void Reset()
}
</code></pre>
<p>Das könnte in C++ in etwa so aussehen:</p>
<pre><code>template&lt;typename T&gt;
class Iter
{
public:
    // iterate over range given by [begin .. end)
    Iter(iterator_for_T begin, iterator_for_T end);

    // iterate over full container
    template&lt;typename Container&gt;
    Iter(Container&amp; container) : Iter(container.begin(), container.end()) {}

    // ...
    // whatever constructor comes to mind
    // ...

    // IEnumerator&lt;T&gt;.Current is valid and last IEnumerator&lt;T&gt;.MoveNext() succeeds
    operator bool();

    // IEnumerator&lt;T&gt;.Current
    T&amp; operator*();

    // IEnumerator&lt;T&gt;.MoveNext()
    Iter&lt;T&gt;&amp; Operator++();
}
</code></pre>
<p>Der Trick mit so einer Konstruktion:<br />
Man hat eine kompakte Einheit (in diesem Fall für einen Forward-Iterator)<br />
und die Anwendung fühlt sich sehr viel natürlicher an:</p>
<pre><code>Iter&lt;char&gt; it = // ... besorge iterator (z.B. Iter&lt;char&gt;(std::string(&quot;abc&quot;)))

while (++it)
{
    tu_was_mit_char_iterator(it);
    tu_was_mit_char(*it);
}

it.reset();

if (++it)
{
    switch(*it)
    {
        case 'a':
            if (++it &amp;&amp; *it == 'b')
                cout &lt;&lt; &quot;\&quot;ab\&quot; found&quot; &lt;&lt; endl;
            else
                cout &lt;&lt; &quot;'a' not followed by 'b'&quot; &lt;&lt; endl;
            break;
    }
}
else
{
    cout &lt;&lt; &quot;it is empty&quot; &lt;&lt; endl;
}
</code></pre>
<p>Wichtig für mich: kein gefuckle mit so einem begin()/end() Pärchen, der<br />
Container interessiert mich nicht die Bohne (ich will einfach nur über die<br />
Elemente iterieren), und das obige Schema lässt sich dann wohl auch beliebig<br />
für vorwärts/rückwärts/random/const/was_weis_ich iteratoren erweitern/anpassen.</p>
<p>Währe schön, wenn ein template-ler mir bei der Implementierung unter die<br />
Arme greifen könnte.</p>
<p>Danke<br />
Knut</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/320133/c-ienumerator-in-c</link><generator>RSS for Node</generator><lastBuildDate>Fri, 24 Jul 2026 12:07:41 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/320133.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 17 Sep 2013 18:24:53 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to c# IEnumerator in c++ on Tue, 17 Sep 2013 18:24:53 GMT]]></title><description><![CDATA[<p>Hallo Leute,</p>
<p>ich versuche so eine Art CLR IEnumerator in C++ abzubilden. Ich werde mit<br />
templates und traits so langsam besser, aber so ganz reichts wohl noch nicht.<br />
Das IEnumerator Interface sieht in C# in etwa so aus:</p>
<pre><code>public interface IEnumerator&lt;T&gt;
{
    // Returns true, if MoveNext() succeeds and Current is a valid T
    bool MoveNext();
    // a valid T if the previous MoveNext() succeeds
    T Current { get; }
    // Returns to Initial state
    void Reset()
}
</code></pre>
<p>Das könnte in C++ in etwa so aussehen:</p>
<pre><code>template&lt;typename T&gt;
class Iter
{
public:
    // iterate over range given by [begin .. end)
    Iter(iterator_for_T begin, iterator_for_T end);

    // iterate over full container
    template&lt;typename Container&gt;
    Iter(Container&amp; container) : Iter(container.begin(), container.end()) {}

    // ...
    // whatever constructor comes to mind
    // ...

    // IEnumerator&lt;T&gt;.Current is valid and last IEnumerator&lt;T&gt;.MoveNext() succeeds
    operator bool();

    // IEnumerator&lt;T&gt;.Current
    T&amp; operator*();

    // IEnumerator&lt;T&gt;.MoveNext()
    Iter&lt;T&gt;&amp; Operator++();
}
</code></pre>
<p>Der Trick mit so einer Konstruktion:<br />
Man hat eine kompakte Einheit (in diesem Fall für einen Forward-Iterator)<br />
und die Anwendung fühlt sich sehr viel natürlicher an:</p>
<pre><code>Iter&lt;char&gt; it = // ... besorge iterator (z.B. Iter&lt;char&gt;(std::string(&quot;abc&quot;)))

while (++it)
{
    tu_was_mit_char_iterator(it);
    tu_was_mit_char(*it);
}

it.reset();

if (++it)
{
    switch(*it)
    {
        case 'a':
            if (++it &amp;&amp; *it == 'b')
                cout &lt;&lt; &quot;\&quot;ab\&quot; found&quot; &lt;&lt; endl;
            else
                cout &lt;&lt; &quot;'a' not followed by 'b'&quot; &lt;&lt; endl;
            break;
    }
}
else
{
    cout &lt;&lt; &quot;it is empty&quot; &lt;&lt; endl;
}
</code></pre>
<p>Wichtig für mich: kein gefuckle mit so einem begin()/end() Pärchen, der<br />
Container interessiert mich nicht die Bohne (ich will einfach nur über die<br />
Elemente iterieren), und das obige Schema lässt sich dann wohl auch beliebig<br />
für vorwärts/rückwärts/random/const/was_weis_ich iteratoren erweitern/anpassen.</p>
<p>Währe schön, wenn ein template-ler mir bei der Implementierung unter die<br />
Arme greifen könnte.</p>
<p>Danke<br />
Knut</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353238</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353238</guid><dc:creator><![CDATA[knutjelitto]]></dc:creator><pubDate>Tue, 17 Sep 2013 18:24:53 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Tue, 17 Sep 2013 18:50:27 GMT]]></title><description><![CDATA[<p>Hast du eine bestimmte Frage? Denn nur dann kann man dir auch helfen. Viel mehr Templates brauchst du ja nicht. Einen solchen Enumerator in C++ zu bauen macht im übrigen nur dann Sinn, wenn du ein höheres Abstraktionsniveau brauchst (z.B. mit Polymorphie), ansonsten sind Iteratoren schon schön. Vor allem erlauben die ab C++11 mit begin/end das for-each.</p>
<p>Btw: Iteratoren beginnen in C++ beim ersten und enden nach dem letzten Element. Enumeratoren von .NET beginnen vor dem ersten und enden beim letzten Element.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353246</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353246</guid><dc:creator><![CDATA[*rant*]]></dc:creator><pubDate>Tue, 17 Sep 2013 18:50:27 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Tue, 17 Sep 2013 19:27:24 GMT]]></title><description><![CDATA[<p>@/rant/</p>
<p>Frage: wie allgemein implementieren?</p>
<p>Und: ich find x.begin()/x.end() eigentlich NICHT schön <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>z.B (for-each jetzt mal außen vor - begin()/end() kann man immer noch exponieren):</p>
<pre><code>std::string x(&quot;abc&quot;);
auto current = x.begin();
while (current != x.end())
{
    cout &lt;&lt; *current &lt;&lt; endl;
    ++current;
    // und wir schreiben NICHT *current++ oder so
}
</code></pre>
<p>versus</p>
<pre><code>auto it = Iter(std::string(&quot;abc&quot;));
while (++it)
{
    cout &lt;&lt; *it &lt;&lt; endl;
}
</code></pre>
<p>Die zweite Version sieht für mich irgendwie ``schöner´´ aus</p>
<p>Und: der simple for-each Fall interessiert mich jetzt eigentlich nicht so sehr.</p>
<p>Gruss<br />
Knut</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353256</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353256</guid><dc:creator><![CDATA[knutjelitto]]></dc:creator><pubDate>Tue, 17 Sep 2013 19:27:24 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Tue, 17 Sep 2013 19:45:54 GMT]]></title><description><![CDATA[<p>knutjelitto schrieb:</p>
<blockquote>
<p>Und: ich find x.begin()/x.end() eigentlich NICHT schön <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>Man kann sie aber in Algorithmen einsetzen. Das System ist sehr flexibel und damit schön. Das wirst du mit deinem Konzept nicht erreichen können. Es macht auch keinen Sinn, C++ die C#/Java Syntax aufzwingen zu wollen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353259</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353259</guid><dc:creator><![CDATA[Mechanics]]></dc:creator><pubDate>Tue, 17 Sep 2013 19:45:54 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Tue, 17 Sep 2013 19:47:33 GMT]]></title><description><![CDATA[<p>Das Beispiel mit begin/end lautet aber in C++11 idealerweise wie folgt (und das finde ich am schönsten):</p>
<pre><code class="language-cpp">std::string x(&quot;abc&quot;);
for (auto current : x)
    cout &lt;&lt; current &lt;&lt; endl;
</code></pre>
<p>Bezüglich der allgemeinen Implementierung: Speicher 3 Iteratoren als Instanzvariablen im Enumerator: begin, end und current. Ich würde mich verhaltensmässig an den C++ Iteratoren orientieren und am Anfang gleich current = begin setzen. Und dann halt als move jeweils ++current und return end == current. Merke: Das Verhalten ist dann aber anders als bei .NET. Dort wäre current am Anfang null.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353261</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353261</guid><dc:creator><![CDATA[*rant*]]></dc:creator><pubDate>Tue, 17 Sep 2013 19:47:33 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Tue, 17 Sep 2013 20:04:48 GMT]]></title><description><![CDATA[<p>/rant/ schrieb:</p>
<blockquote>
<p>Das Beispiel mit begin/end lautet aber in C++11 idealerweise wie folgt (und das finde ich am schönsten):</p>
<pre><code class="language-cpp">std::string x(&quot;abc&quot;);
for (auto current : x)
    cout &lt;&lt; current &lt;&lt; endl;
</code></pre>
<p>Bezüglich der allgemeinen Implementierung: Speicher 3 Iteratoren als Instanzvariablen im Enumerator: begin, end und current. Ich würde mich verhaltensmässig an den C++ Iteratoren orientieren und am Anfang gleich current = begin setzen. Und dann halt als move jeweils ++current und return end == current. Merke: Das Verhalten ist dann aber anders als bei .NET. Dort wäre current am Anfang null.</p>
</blockquote>
<p>Ja, ja, sowas in der Art habe ich schon implementiert, ist ja kein Problem.</p>
<p>Das Problem ist doch aber:</p>
<p>Wie erzeuge ich aus einem beliebigen iterator-Paar einen Iter&lt;T&gt;?</p>
<p>also wie komme ich von z.B.<br />
vector&lt;bum&gt; auf einen Iter&lt;bum&gt; über vector&lt;bum&gt;.begin()/vector&lt;bum&gt;.end():</p>
<pre><code>vector&lt;bum&gt; vum{ ... bla ...};

Iter&lt;bum&gt; it = create_iter(vum.begin() + 12, vum.begin() + 26);
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2353264</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353264</guid><dc:creator><![CDATA[knutjelitto]]></dc:creator><pubDate>Tue, 17 Sep 2013 20:04:48 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Tue, 17 Sep 2013 20:17:16 GMT]]></title><description><![CDATA[<p>vum.begin() erzeugt automatisch einen Iterator vom richtigen Typ. Super, oder?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353267</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353267</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Tue, 17 Sep 2013 20:17:16 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Wed, 18 Sep 2013 10:41:34 GMT]]></title><description><![CDATA[<p>knutjelitto schrieb:</p>
<blockquote>
<p>Das Problem ist doch aber:</p>
<p>Wie erzeuge ich aus einem beliebigen iterator-Paar einen Iter&lt;T&gt;?</p>
</blockquote>
<p>Wieso musst du überhaupt ein Iter&lt;T&gt; erzeugen? Musst Du doch gar nicht. Trenn Dich von Deiner C#-Denke. Vererbung und Polymorphie ist nicht die einzige Art der Abstraktion, die C++ Dir bietet. Als ich von Java auf C++ umsteig, habe ich auch erstmal zig Interfaces geschrieben, weil ich es von Java gewohnt war. Es gibt aber keinen guten Grund, gleich von Anfang an, den Nutzern eine Indirektion mit virtuellen Funktionen aufzuzwingen.</p>
<p>Meine Botschaft an Dich: Programmiere C++, nicht C# in C++.</p>
<p>Wenn Du mit einer anderen Schnittstelle für Iteration experimentieren willst, kannst du einen Wrapper verwenden. <a href="http://ideone.com/KDtov5" rel="nofollow">So kann das aussehen</a>. Das lässt sich später immer noch per <em>Type Erasure</em> verallgemeinern, <em>wenn du es brauchst</em>. Das würde ich aber optional machen und den Anwendern nicht von vorn herein aufzwingen. Mit <em>Type Erasure</em> kannst du dann z.B. aus einem Funktions-Template wie diesem</p>
<pre><code class="language-cpp">template&lt;class JavaIter&gt;
void zeig(JavaIter ji)
{
    while (ji.hasNext()) {
        cout &lt;&lt; ji.next() &lt;&lt; endl;
    }
}
</code></pre>
<p>so eine Funktion bauen:</p>
<pre><code class="language-cpp">void zeig(any_java_iter&lt;int&gt; ji)
{
    while (ji.hasNext()) {
        cout &lt;&lt; ji.next() &lt;&lt; endl;
    }
}
</code></pre>
<p>wobei <code>any_java_iter&lt;int&gt;</code> per Indirektion und Laufzeit-Polymorphie den wahren Typen <code>java_iter_wrapper&lt;vector&lt;int&gt;::iterator&gt;</code> verstecken kann. Iterieren willst du aber eventuell ganz flott und da würde die erforderliche Indirektion zum verstecken des wahren Typs im Wege stehen. Deswegen verwenden wir in C++ meist den wahren Iterator-Typen direkt, ohne ihn zu verstecken.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353316</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353316</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Wed, 18 Sep 2013 10:41:34 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Wed, 18 Sep 2013 08:17:58 GMT]]></title><description><![CDATA[<p>knutjelitto schrieb:</p>
<blockquote>
<p>Die zweite Version sieht für mich irgendwie ``schöner´´ aus</p>
</blockquote>
<p>Irrelevant! Es ist nicht idiomatisch. Wenn Du Außenseiter spielen willst, der die Sprache C++ ganz anders verwerwendet als andere, nur zu. Beschwer Dich dann aber nicht, wenn keiner mit Dir zusammenarbeiten will.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353321</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353321</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Wed, 18 Sep 2013 08:17:58 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Wed, 18 Sep 2013 10:00:29 GMT]]></title><description><![CDATA[<p>Irgendwie so vielleicht:<br />
<a href="http://ideone.com/Frl33B" rel="nofollow">http://ideone.com/Frl33B</a></p>
<p>Da fehlt noch einiges, zum Beispiel sollte operator * const werden und eine const-Referenz zurückgeben, aber ich komme mit typename, decltype und so noch nicht genug klar um das mal eben hinzukriegen. So ganz verstehe ich aber auch nicht warum man zwei Iteratoren nimmt wenns auch einer tut, zumal ein einzelner Iterator bei Containern, die schwer an ihren end-Iterator rankommen, (wie verketteten Listen) effizienter wäre.</p>
<pre><code>#include &lt;iostream&gt;
#include &lt;cassert&gt;
#include &lt;vector&gt;
#include &lt;type_traits&gt;
using namespace std;

template&lt;class C&gt;
struct Iterator{
	operator bool() const{
		return startiterator != enditerator;
	}
	const Iterator &amp;operator ++(){
		assert(*this);
		startiterator++;
		return *this;
	}
	const Iterator operator ++(int){
		Iterator other(*this);
		startiterator++;
		return other;
	}
	typename C::iterator startiterator, enditerator;
	//typename C::iterator sollte durch decltype(C::begin()) oder so ersetz werden
	Iterator(C &amp;c) : startiterator(c.begin()), enditerator(c.end()){
	}

	auto operator *() -&gt; decltype(*startiterator){
		//hier muss man noch was mit add_const und add_rvalue_reference machen
		return *startiterator;
	}
};

//Am ende den ganzen Spaß nochmal für const-Iterator

int main(){
	vector&lt;int&gt; v = {42, 37, 128};
	Iterator&lt;vector&lt;int&gt;&gt; it(v); //kann man noch in eine makeIterator-Funktion tun
	while (it){
		cout &lt;&lt; *it &lt;&lt; ' ';
		it++;
	}
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2353352</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353352</guid><dc:creator><![CDATA[nwp3]]></dc:creator><pubDate>Wed, 18 Sep 2013 10:00:29 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Wed, 18 Sep 2013 10:35:43 GMT]]></title><description><![CDATA[<p>@npw3: So finde ich es besser:</p>
<pre><code>#include &lt;iterator&gt;

template&lt; typename Iter &gt;
struct Iterator
{
	using underlying_iterator = Iter;

private:

    mutable underlying_iterator first,
                          last;

public:

	underlying_iterator begin() { return first; }
	underlying_iterator end() { return last; }

    operator bool() const
    {
        return first != last;
    }

    Iterator&amp; operator++()
    {
        ++first;
        return *this;
    }

    Iterator const&amp; operator++() const
    {
        ++first;
        return *this;
    }

    Iterator operator++(int) const
    {
        Iterator other(*this);
        ++first;
        return other;
    }

    explicit Iterator( underlying_iterator first,
					   underlying_iterator last ):
    	first{first},
    	last{last} {}

	template&lt; typename Container &gt;
    Iterator(Container&amp; c) :
    	Iterator{ std::begin(c), std::end(c) } {}

    decltype(*first) operator*()
    {
        return *first;
    }

    decltype(*first) operator*() const
    {
        return *first;
    }
};

#include &lt;vector&gt;
#include &lt;iostream&gt;

int main()
{
    std::vector&lt;int&gt; const v_const = {43, 38, 129};

    Iterator&lt;std::vector&lt;int&gt;::const_iterator&gt; it_const = v_const;

    while (it_const)
        std::cout &lt;&lt; *it_const++ &lt;&lt; ' ';
}
</code></pre>
<p>(<a href="http://ideone.com/j1JtWe" rel="nofollow">Ideone</a>)</p>
<p>Das hat auch den Vorteil, dass ein Iterator als Argument von begin()/end() gültig ist, sowie dass <code>Iterator&lt;iterator&gt; const</code> dieselben Möglichkeiten hat wie <code>Iterator&lt;const_iterator&gt;</code> - man kann also einen Iterator&lt;iterator&gt; bequem als Klassenmember halten.</p>
<blockquote>
<p>//hier muss man noch was mit add_const und add_rvalue_reference machen</p>
</blockquote>
<p>Muss man das? Wieso?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353360</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353360</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Wed, 18 Sep 2013 10:35:43 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Wed, 18 Sep 2013 10:34:46 GMT]]></title><description><![CDATA[<p>Das ist dann aber eher eine Range als ein Iterator.</p>
<p>Gibt es auch schon in ähnlicher Form als <code>boost::iterator_range</code> .</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353362</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353362</guid><dc:creator><![CDATA[Nexus]]></dc:creator><pubDate>Wed, 18 Sep 2013 10:34:46 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Wed, 18 Sep 2013 10:56:52 GMT]]></title><description><![CDATA[<p>Nexus schrieb:</p>
<blockquote>
<p>Das ist dann aber eher eine Range als ein Iterator.</p>
</blockquote>
<p>Ist mir schon klar - darauf wollte ich ja hinaus. <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>Gibt es auch schon in ähnlicher Form als boost::iterator_range.</p>
</blockquote>
<p>Ja, kenne ich.</p>
<p>Edit: Bei näherer Betrachtung ist das Design hässlich. const-correctness sehe ich auch nirgends..</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353364</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353364</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Wed, 18 Sep 2013 10:56:52 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Wed, 18 Sep 2013 14:32:56 GMT]]></title><description><![CDATA[<p>Hier noch ein paar Kommentare zu dem, was man hier gerade sehen konnte:</p>
<p>@nwp3:</p>
<ul>
<li>Ich finde es unschön, dass Dein Klassentemplate einen Containertypen als Templateargument statt eines Iterator-Typen erwartet. So hast du bei rohen Arrays z.B. je Größe N verschiedene Typen ( <code>Iterator&lt;T[N]&gt;</code> ). Es gibt auch noch &quot;scary iterators&quot;, also Iteratoren gleichen Typs von verschiedenartigen Containern. Zum Beispiel interessiert dich beim Iterieren nicht mehr, as für ein Allokator verwendet wurde, also sollte davon auch nix im Typ zu sehen sein. Andernfalls kann der Template-Bloat unnötig groß werden.</li>
<li>Dein <code>operator bool</code> ist nicht <code>explicit</code></li>
<li>Du verwendest c.begin(), c.end() statt begin(c), end(c). Klappt dann auch gar nicht auf rohen Arrays</li>
</ul>
<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/28547">@Sone</a>:</p>
<ul>
<li><code>operator bool</code> ist bei dir auch nicht <code>explicit</code></li>
<li>Im Wesentlichen ist das sehr ähnlich zu dem, was ich vorher schon verlinkt hatte -- mal von der Schnittstelle des &quot;Iterators&quot; abgesehen ( <code>hasNext</code> statt <code>operator bool</code> , etc etc etc)</li>
<li>Du qualifizierst begin und end und schaltest damit ADL aus. Das ist ungeschickt. Deswegen wirst du u.a. &quot;using std::begin&quot; in dem finden, was ich verlinkte.</li>
</ul>
<p>gruß,<br />
kk</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353374</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353374</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Wed, 18 Sep 2013 14:32:56 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Wed, 18 Sep 2013 11:01:43 GMT]]></title><description><![CDATA[<blockquote>
<p>Du qualifizierst begin und end und schaltest damit ADL aus. Das ist ungeschickt.</p>
</blockquote>
<p>Wieso? <code>std::begin</code> findet es trotzdem durch SFINAE.</p>
<blockquote>
<p>operator bool ist bei dir auch nicht explicit</p>
</blockquote>
<p>Das ist Absicht. Wieso sollte ich <code>bool(iter)</code> in einer Bedingung stehen haben?</p>
<p>Wie gesagt, ich finde mein Design nicht sehr hübsch, auf den zweiten Blick. Aber nicht aus diesen Gründen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353381</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353381</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Wed, 18 Sep 2013 11:01:43 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Wed, 18 Sep 2013 12:27:44 GMT]]></title><description><![CDATA[<p>Sone schrieb:</p>
<blockquote>
<blockquote>
<p>Du qualifizierst begin und end und schaltest damit ADL aus. Das ist ungeschickt.</p>
</blockquote>
<p>Wieso? <code>std::begin</code> findet es trotzdem durch SFINAE.</p>
</blockquote>
<p>Die Begründung hast du beim Zitat weggelassen. Es geht um ADL. Dadurch, dass du <code>begin</code> und <code>end</code> mit <code>std::</code> qualifizierst, beschränkst du Dich auf <code>begin</code> / <code>end</code> -Funktionen, die im <code>std</code> -Namensraum deklariert wurden. Damit sind andere <code>begin</code> / <code>end</code> Funktionen, die woanders deklariert wurden und ohne Qualifizierung über ADL hätten gefunden werden können, für Dich unerreichbar. Interessant wird das für Typen, die keine begin/end-Elementfunktionen besitzen, aber freie begin/end-Funktionen imselben Namensraum anbieten.</p>
<p>Sone schrieb:</p>
<blockquote>
<blockquote>
<p>operator bool ist bei dir auch nicht explicit</p>
</blockquote>
<p>Das ist Absicht. Wieso sollte ich <code>bool(iter)</code> in einer Bedingung stehen haben?</p>
</blockquote>
<p>Da liegt bei dir wohl ein Missverständnis vor. Ein <code>explicit operator bool()</code> zwingt Dich nicht in Bedingungen, <code>bool(iter)</code> zu schreiben. Es unterdrückt lediglich diese blöden Situationen(*), die man sich früher nur mit dem &quot;safe bool&quot;-Idiom vom Hals halten konnte. Das C++11 Feature &quot;explicit conversion operators&quot; gibt es genau aus diesem Grund. Du wirst feststellen, dass std::unique_ptr und std::shared_ptr auch so einen <code>explicit operator bool()</code> haben. Boolsche Kontexte wie bei <code>if</code> , <code>while</code> , <code>&amp;&amp;</code> u.s.w. kommen auch mit einem <code>explicit operator bool()</code> klar.</p>
<p>(* blöd:</p>
<pre><code class="language-cpp">deiniterator &lt;&lt; 3; // upps, das kompiliert ja sogar!
</code></pre>
<p>)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353414</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353414</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Wed, 18 Sep 2013 12:27:44 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Wed, 18 Sep 2013 12:25:12 GMT]]></title><description><![CDATA[<p>@nwp3, <a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/28547">@Sone</a>:</p>
<p>Vielen dank, ist so im groben das, was ich mir zuerst auch so zurecht gefrickelt hatte <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/24868">@krümelkacker</a>:<br />
Man kann eben nicht so leicht über seinen Schatten springen. Ich mach' jetzt seit über 10 Jahren in C# und OOP sitzt einem da tief in den Knochen. Generika sind in C# eher mittel zum Zweck und eine ordentliche Grundlage um OO zu programmieren. Habe in der Zwischenzeit was implementiert, was meinem Bedürfnis nach Objectorientierung entgegenkommt. Ich wusste nicht, das sowas in der Art ``type erasure´´ heißt (falls ich das richtig verstanden habe). Das ist alles andere als produktionsreifer Code, über die grossen 3/5 habe ich mir im zusammenspiel mit unique_ptr&lt;&gt; auch noch nicht wirklich Gedanken gemacht, aber hey C#/Windows@work &amp; C++/Linux/Embedded@home und wenn mir das auf meinem Mikrocontroller Probleme macht wird's halt verbessert. <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>Habe hier 'nen Link zu 'nem ähnlich alten Knochen wie mich gefunden:<br />
<a href="http://www.artima.com/cppsource/type_erasure.html" rel="nofollow">http://www.artima.com/cppsource/type_erasure.html</a><br />
Der sieht das ganze auch eher entspannt.</p>
<pre><code>#pragma once

#include &lt;memory&gt;

namespace kp
{
	namespace lang
	{
		template&lt;typename T&gt;
		class Iter
		{
		public:
			typedef T value_type;
			typedef T&amp; reference;

			class IterImpl;

			Iter(IterImpl* impl) : m_impl(impl)
			{
			}

			template&lt;typename container&gt;
			static Iter&lt;T&gt; create(container&amp; cont)
			{
				return Iter(new ContainerIter&lt;container&gt;(cont.begin(), cont.end()));
			}

			template&lt;typename container&gt;
			static Iter&lt;T&gt; create(container&amp; cont, typename container::iterator begin, typename container::iterator end)
			{
				return Iter(new ContainerIter&lt;container&gt;(begin, end));
			}

			operator bool() const
			{
				return m_impl-&gt;valid();
			}

			reference operator*()
			{
				return m_impl-&gt;current();
			}

			reference operator-&gt;()
			{
				return m_impl-&gt;current();
			}

			bool operator++()
			{
				return m_impl-&gt;next();
			}

			class IterImpl
			{
			public:
				virtual bool valid() const = 0;
				virtual reference current() = 0;
				virtual bool next() = 0;
				virtual ~IterImpl() {}
			};

			template&lt;typename container&gt;
			class ContainerIter : public IterImpl
			{
			public:
				typedef typename container::iterator iterator;

				ContainerIter(iterator begin, iterator end)
					: m_init(false), m_begin(begin), m_end(end)
				{
				}

				bool valid() const override
				{
					return m_init &amp;&amp; m_current != m_end;
				}

				reference current() override
				{
					return *m_current;
				}

				bool next() override
				{
					if (m_init &amp;&amp; m_current != m_end)
					{
						++m_current;
					}
					else
					{
						m_current = m_begin;
						m_init = true;
					}
					return m_current != m_end;
				}
			private:
				bool m_init;
				iterator m_begin;
				iterator m_end;
				iterator m_current;
			};
		private:
			std::unique_ptr&lt;IterImpl&gt; m_impl;
		};
	}
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2353416</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353416</guid><dc:creator><![CDATA[knutjelitto]]></dc:creator><pubDate>Wed, 18 Sep 2013 12:25:12 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Wed, 18 Sep 2013 12:29:17 GMT]]></title><description><![CDATA[<p>Oh? Ich dachte, in Bedingungen wie bei <code>if</code> -Statements muss das Argument implizit nach <code>bool</code> konvertiert werden. Vielen Dank für die Aufklärung.</p>
<blockquote>
<p>Die Begründung hast du beim Zitat weggelassen. Es geht um ADL. Dadurch, dass du begin und end mit std:: qualifizierst, beschränkst du Dich auf begin/end-Funktionen, die im std-Namensraum deklariert wurden. Damit sind andere begin/end Funktionen, die woanders deklariert wurden und ohne Qualifizierung über ADL hätten gefunden werden können, für Dich unerreichbar. Interessant wird das für Typen, die keine begin/end-Elementfunktionen besitzen, aber freie begin/end-Funktionen imselben Namensraum anbieten.</p>
</blockquote>
<p>Ach, Quatsch! Da habe ich was missverstanden! Ich dachte, du meinst das begin/end , welches ich als Memberfunktion deklariert habe...<br />
Mir ist durchaus klar, was es mit dem ADL-Problem von <code>std::swap</code> und <code>std::begin</code> / <code>end</code> auf sich hat. Ich vergesse es nur immer wieder.</p>
<p>Dass ich das <code>begin</code> / <code>end</code> im <strong>Konstruktor von <code>Iterator</code></strong> unqualifiziert nutzen sollte, habe ich übersehen, auch Danke dafür, korrigiere ich gleich.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353417</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353417</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Wed, 18 Sep 2013 12:29:17 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Wed, 18 Sep 2013 12:51:10 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/30025">@knutjelitto</a>: Wie gesagt, du versuchst zwei orthogonale Dinge aufeinmal zu machen. Wie gesagt, es ist besser, diese zwei Dinge zu trennen. Einmal ein leichtgewichtiges Objekt, was zwei C++-Iteratoren (ohne Type Erasure) kapselt und eine Schnittstelle anbietet, die dir besser gefällt (ich rate aber immer noch davon ab, schau dir mal Boost.Range an) und zum anderen willst Du ggf. (aber nicht oft!) den dynamischen Typen (und damit die Info, was für ein Container das war) verstecken. Das lässt sich separat lösen. Auch bei dir sollte der Konvertierungsoperator <code>explicit</code> sein. Da könnte man sogar glatt eine Compiler-Warnung draus machen. Wenn Du im C++11-Modus schreibst</p>
<pre><code class="language-cpp">...
  operator bool() const { ...
  ...
</code></pre>
<p>dann sollte da höchstwahrscheinlich wirklich</p>
<pre><code class="language-cpp">...
  explicit operator bool() const { ...
  ...
</code></pre>
<p>stehen. Dann überlädst du operator++ noch auf eine Art, die nichts mit dem zu tun hat, was man von operator++ normalerweise erwartet. Von operator++ erwartet man nicht einen boolschen Wert zurück.</p>
<p>Versuch mal Type Erasure als <em>Ergänzung</em> (nicht <em>Modifikation</em>) zu dem von mir <a href="http://ideone.com/KDtov5" rel="nofollow"><em>verlinkten</em></a> Code-Beispiel zu schreiben, also ein neues Klassen-Template <code>any_java_iter</code> , so dass ein <code>any_java_iter&lt;int&gt;</code> ein <code>java_iter_wrapper&lt;std::vector&lt;int&gt;::iterator&gt;</code> kapseln kann. -- Aber es sieht eigentlich so aus, als ob du damit keine Schwierigkeiten mehr haben solltest. <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>Sone schrieb:</p>
<blockquote>
<p>Vielen Dank für die Aufklärung.</p>
</blockquote>
<p>No problem. <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/2353426</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353426</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Wed, 18 Sep 2013 12:51:10 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Wed, 18 Sep 2013 13:00:44 GMT]]></title><description><![CDATA[<p>Sone schrieb:</p>
<blockquote>
<p>Oh? Ich dachte, in Bedingungen wie bei <code>if</code> -Statements muss das Argument implizit nach <code>bool</code> konvertiert werden. Vielen Dank für die Aufklärung.</p>
</blockquote>
<p>Kapitel 4 Absatz 3 Satz 2 f.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353431</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353431</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Wed, 18 Sep 2013 13:00:44 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Wed, 18 Sep 2013 13:09:55 GMT]]></title><description><![CDATA[<p><a class="plugin-mentions-user plugin-mentions-a" href="https://www.c-plusplus.net/forum/uid/24868">@krümelkacker</a>:</p>
<p>explicit - ich fummel hier im Augenblick mit MSVC++ rum, da kann man nicht so wirklich C++11 Sachen machen <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>Operator++ - war 'ne Kurzschlusshandlung. Habe mich am gebrauch orientiert, und bisher nur</p>
<pre><code>if (++it) ...
</code></pre>
<p>oder</p>
<pre><code>while (++it) ...
</code></pre>
<p>verwendet.</p>
<p>Habe den Code erstmal so runtergeschrieben. Ist noch nicht wirklich so strukturiert, wie ich das haben möchte. Und es zweistufig zu machen ist wohl 'ne gute Idee.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353434</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353434</guid><dc:creator><![CDATA[knutjelitto]]></dc:creator><pubDate>Wed, 18 Sep 2013 13:09:55 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Wed, 18 Sep 2013 13:47:21 GMT]]></title><description><![CDATA[<p>camper schrieb:</p>
<blockquote>
<p>Kapitel 4 Absatz 3 Satz 2 f.</p>
</blockquote>
<p>Ich war zuerst völlig verwirrt, aber dann habe ich selbst nachgeschlagen:</p>
<p>§6.4 schrieb:</p>
<blockquote>
<p>The value of a condition that is an expression is the value of the expression, <strong>contextually converted</strong> to bool for statements other than switch</p>
</blockquote>
<p>Und dann... §4/3:</p>
<blockquote>
<p>Certain language constructs require that an expression be converted to a Boolean value. An expression e appearing in such a context is said to be <strong>contextually converted</strong> to bool and is well-formed if and only if the declaration bool t(e); is well-formed, for some invented temporary variable t (8.5).</p>
</blockquote>
<p>Hätte ich auch selbst nachschlagen können :p</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353442</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353442</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Wed, 18 Sep 2013 13:47:21 GMT</pubDate></item><item><title><![CDATA[Reply to c# IEnumerator in c++ on Wed, 18 Sep 2013 14:33:41 GMT]]></title><description><![CDATA[<p>upps, habe statt auf edit einfach auf zitieren geklickt. hier gibt's nix zu sehen, habe nur auf seite 2 einen hinweis bzgl scary iterators hinzugefügt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2353451</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2353451</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Wed, 18 Sep 2013 14:33:41 GMT</pubDate></item></channel></rss>