<?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[Undefiniertes Verhalten bei &amp;quot;Closures&amp;quot; (structs mit operator()), wenn sie stateful sind???]]></title><description><![CDATA[<p>Servus,</p>
<p>ich beiß' hier gerade in die Tischkante, weil ich ein Problem mit Funktoren habe, was offenbar auf undefiniertes Verhalten zurückzuführen ist.</p>
<p>Ich versuche mal ein Minimalbeispiel:<br />
Es gibt eine Klasse, die zwei Pointer auf Structs speichert, die jeweils den Klammeroperator überladen. Zwei Pointer, weil es eine Vorwärts- und eine Rückwärtskonvertierung gibt:</p>
<pre><code class="language-cpp">class Foo
{
public:
    struct Bar
    {
        virtual ~ConverterFunctor() {}
        virtual int operator()(int) const = 0;
    };
    Foo(Bar* f1, Bar* f2):
        mf1(f1),
        mf2(f2)
    {}
    int calc1(int val) const { return (*mf1)(val); }
    int calc2(int val) const { return (*mf2)(val); }
private:
    Bar* mf1;
    Bar* mf2;
};
</code></pre>
<p>Dann gibts verschiedene konkrete Klassen, die alle andere Funktoren definieren, bspws:</p>
<pre><code class="language-cpp">class ConcreteFoo : public Foo 
{
    struct Forward : public Foo::Bar {
        int operator()(int val) const { /* tatsächliche Berechnung */ }
    };

    struct Backward : public Foo::Bar {
        int operator()(int) const { /* umkehrung der Berechnung */ }
    };

public:
    ConcreteFoo(): Foo(new Forward, new Backward) {}
};
</code></pre>
<p>Aufgerufen wird das ganze von einer Klasse, die einen Pointer auf Foo speichert:</p>
<pre><code class="language-cpp">class User {
    User(Foo* foo): m_foo(foo) {}
    int doSomething() { return m_foo-&gt;calc1(m_some_value); }
private:
    std::auto_ptr&lt;Foo&gt; m_foo;
    int m_some_value;
};
</code></pre>
<p>Gratulation, wer bis hierhin durchgehalten hat.<br />
Jetzt wirds nämlich spannend: Das funktioniert alles so lange, wie die Funktoren &quot;stateless&quot; sind. Sobald ich aber einen Functor definiere, der eine Membervariable hat, die zur Berechnung hinzugezogen wird (natürlich nur lesend, die operator()-Funktionen sind ja const!), kommt nur noch Blödsinn raus.<br />
In einer printf-Orgie hab ich jetzt festgestellt, das sämtliche Instantiierungen eines Funktors mit Membervariable ALLE den GLEICHEN wert in dieser Membervariable haben, egal wie ich sie instantiiert habe.</p>
<p>Beispiel:</p>
<pre><code class="language-cpp">class SomeConcreteFoo : public Foo 
{
    struct Stateful : public Foo::Bar {
        Stateful(int i):member(i) {Log(member); /* -&gt; hier kommt der richtige Wert! */}
        int operator()(int val) const { Log(member); /* -&gt; hier kommt immer 1! WTF? */ }
    private:
        int member;
    };

public:
    SomeConcreteFoo(): Foo(new Stateful(42), new Stateful(23)) {}
};
</code></pre>
<p>Wo habe ich hier Mist gebaut? Wird da irgendwo ein Objekt gesliced? Passiert da irgendwo eine Kopie, die ich übersehen habe?</p>
<p>Philipp</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/268457/undefiniertes-verhalten-bei-quot-closures-quot-structs-mit-operator-wenn-sie-stateful-sind</link><generator>RSS for Node</generator><lastBuildDate>Tue, 01 Sep 2026 20:18:41 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/268457.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 09 Jun 2010 13:05:42 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Undefiniertes Verhalten bei &amp;quot;Closures&amp;quot; (structs mit operator()), wenn sie stateful sind??? on Wed, 09 Jun 2010 13:20:01 GMT]]></title><description><![CDATA[<p>Servus,</p>
<p>ich beiß' hier gerade in die Tischkante, weil ich ein Problem mit Funktoren habe, was offenbar auf undefiniertes Verhalten zurückzuführen ist.</p>
<p>Ich versuche mal ein Minimalbeispiel:<br />
Es gibt eine Klasse, die zwei Pointer auf Structs speichert, die jeweils den Klammeroperator überladen. Zwei Pointer, weil es eine Vorwärts- und eine Rückwärtskonvertierung gibt:</p>
<pre><code class="language-cpp">class Foo
{
public:
    struct Bar
    {
        virtual ~ConverterFunctor() {}
        virtual int operator()(int) const = 0;
    };
    Foo(Bar* f1, Bar* f2):
        mf1(f1),
        mf2(f2)
    {}
    int calc1(int val) const { return (*mf1)(val); }
    int calc2(int val) const { return (*mf2)(val); }
private:
    Bar* mf1;
    Bar* mf2;
};
</code></pre>
<p>Dann gibts verschiedene konkrete Klassen, die alle andere Funktoren definieren, bspws:</p>
<pre><code class="language-cpp">class ConcreteFoo : public Foo 
{
    struct Forward : public Foo::Bar {
        int operator()(int val) const { /* tatsächliche Berechnung */ }
    };

    struct Backward : public Foo::Bar {
        int operator()(int) const { /* umkehrung der Berechnung */ }
    };

public:
    ConcreteFoo(): Foo(new Forward, new Backward) {}
};
</code></pre>
<p>Aufgerufen wird das ganze von einer Klasse, die einen Pointer auf Foo speichert:</p>
<pre><code class="language-cpp">class User {
    User(Foo* foo): m_foo(foo) {}
    int doSomething() { return m_foo-&gt;calc1(m_some_value); }
private:
    std::auto_ptr&lt;Foo&gt; m_foo;
    int m_some_value;
};
</code></pre>
<p>Gratulation, wer bis hierhin durchgehalten hat.<br />
Jetzt wirds nämlich spannend: Das funktioniert alles so lange, wie die Funktoren &quot;stateless&quot; sind. Sobald ich aber einen Functor definiere, der eine Membervariable hat, die zur Berechnung hinzugezogen wird (natürlich nur lesend, die operator()-Funktionen sind ja const!), kommt nur noch Blödsinn raus.<br />
In einer printf-Orgie hab ich jetzt festgestellt, das sämtliche Instantiierungen eines Funktors mit Membervariable ALLE den GLEICHEN wert in dieser Membervariable haben, egal wie ich sie instantiiert habe.</p>
<p>Beispiel:</p>
<pre><code class="language-cpp">class SomeConcreteFoo : public Foo 
{
    struct Stateful : public Foo::Bar {
        Stateful(int i):member(i) {Log(member); /* -&gt; hier kommt der richtige Wert! */}
        int operator()(int val) const { Log(member); /* -&gt; hier kommt immer 1! WTF? */ }
    private:
        int member;
    };

public:
    SomeConcreteFoo(): Foo(new Stateful(42), new Stateful(23)) {}
};
</code></pre>
<p>Wo habe ich hier Mist gebaut? Wird da irgendwo ein Objekt gesliced? Passiert da irgendwo eine Kopie, die ich übersehen habe?</p>
<p>Philipp</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1909464</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1909464</guid><dc:creator><![CDATA[PhilippM]]></dc:creator><pubDate>Wed, 09 Jun 2010 13:20:01 GMT</pubDate></item><item><title><![CDATA[Reply to Undefiniertes Verhalten bei &amp;quot;Closures&amp;quot; (structs mit operator()), wenn sie stateful sind??? on Wed, 09 Jun 2010 13:22:45 GMT]]></title><description><![CDATA[<p>Ich kann's leider nicht nachvollziehen. Hast du deinen Fehler bei deinem Beispiel eventuell rausgekürzt? Wenn ich dein Beispiel nämlich zu etwas compilierbarem ergänze:</p>
<pre><code class="language-cpp">#include&lt;iostream&gt;
using namespace std;

class Foo
{
public:
    struct Bar
    {
        virtual ~Bar() {}
        virtual int operator()(int) const = 0;
    };
    Foo(Bar* f1, Bar* f2):
        mf1(f1),
        mf2(f2)
    {}
    int calc1(int val) const { return (*mf1)(val); }
    int calc2(int val) const { return (*mf2)(val); }
private:
    Bar* mf1;
    Bar* mf2;
};	

class SomeConcreteFoo : public Foo
{
    struct Stateful : public Foo::Bar {
      Stateful(int i):member(i) {cout&lt;&lt;&quot;Konstruktor: &quot;&lt;&lt;member&lt;&lt;endl; /* -&gt; hier kommt der richtige Wert! */}
      int operator()(int val) const { cout&lt;&lt;&quot;Operator(): &quot;&lt;&lt; member&lt;&lt;endl; return member;/* -&gt; hier kommt immer 1! WTF? */ }
    private:
        int member;
    };
public:
    SomeConcreteFoo(): Foo(new Stateful(42), new Stateful(23)) {}
};	

class User {
public:
    User(Foo* foo): m_foo(foo) {}
    int doSomething() { return m_foo-&gt;calc1(m_some_value); }
private:
    Foo* m_foo;
    int m_some_value;
}; 

int main()
{
  User test(new SomeConcreteFoo());
  int a = test.doSomething();
  cout&lt;&lt;&quot;Test: &quot;&lt;&lt; a&lt;&lt; endl;
}
</code></pre>
<p>Bekomme ich:</p>
<pre><code>Konstruktor: 23
Konstruktor: 42
Operator(): 42
Test: 42
</code></pre>
<p>Ist das nicht genau das was du möchtest?</p>
<p>edit: Compilier doch mal dein Programm mit extra vielen Compilerwarnungen (&quot;-Wall -Wextra&quot; bei vielen Compilern). Vielleicht findest du ja was.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1909474</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1909474</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Wed, 09 Jun 2010 13:22:45 GMT</pubDate></item><item><title><![CDATA[Reply to Undefiniertes Verhalten bei &amp;quot;Closures&amp;quot; (structs mit operator()), wenn sie stateful sind??? on Wed, 09 Jun 2010 13:29:23 GMT]]></title><description><![CDATA[<p>Ja, sieht so aus, dass ich den Fehler rausekürzt habe.<br />
Was ich rausgekürzt habe, sind die Templates. Da ich aber im Augenblick eh nur die int-instantiierung verwende, sollte das irrelevant sein.</p>
<p>PS:<br />
Mach ich schon: g++ -Werror -Wall -Wextra -pedantic mehr geht eigentlich nicht mehr, außer -Weffc++.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1909478</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1909478</guid><dc:creator><![CDATA[PhilippM]]></dc:creator><pubDate>Wed, 09 Jun 2010 13:29:23 GMT</pubDate></item><item><title><![CDATA[Reply to Undefiniertes Verhalten bei &amp;quot;Closures&amp;quot; (structs mit operator()), wenn sie stateful sind??? on Wed, 09 Jun 2010 13:31:52 GMT]]></title><description><![CDATA[<p>PhilippM schrieb:</p>
<blockquote>
<p>Ja, sieht so aus, dass ich den Fehler rausekürzt habe.<br />
Was ich rausgekürzt habe, sind die Templates. Da ich aber im Augenblick eh nur die int-instantiierung verwende, sollte das irrelevant sein.</p>
<p>PS:<br />
Mach ich schon: g++ -Werror -Wall -Wextra -pedantic mehr geht eigentlich nicht mehr, außer -Weffc++.</p>
</blockquote>
<p>Hmm, dann hilft's wohl nichts, außer ein neues Minimalbeispiel zu erstellen, welches den Fehler noch zeigt. Alles andere wäre Wahrsagerei. Vielleicht findet sich der Fehler dabei ja auch schon von alleine.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1909485</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1909485</guid><dc:creator><![CDATA[SeppJ]]></dc:creator><pubDate>Wed, 09 Jun 2010 13:31:52 GMT</pubDate></item><item><title><![CDATA[Reply to Undefiniertes Verhalten bei &amp;quot;Closures&amp;quot; (structs mit operator()), wenn sie stateful sind??? on Wed, 09 Jun 2010 14:04:49 GMT]]></title><description><![CDATA[<p>Hmpf, wenn ich mir den Wert des this-Zeigers ausgeben lasse, sieht man, dass immer nur das zuerst instantierte Objekt benutzt wird. Alle späteren Objekten werden zwar instantiiert, aber ihr this-Zeiger taucht nie wieder auf.<br />
&quot;I sense an all-night debugging sesion coming&quot;. <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/1909507</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1909507</guid><dc:creator><![CDATA[PhilippM]]></dc:creator><pubDate>Wed, 09 Jun 2010 14:04:49 GMT</pubDate></item><item><title><![CDATA[Reply to Undefiniertes Verhalten bei &amp;quot;Closures&amp;quot; (structs mit operator()), wenn sie stateful sind??? on Wed, 09 Jun 2010 14:20:38 GMT]]></title><description><![CDATA[<p>Fehler gefunden.</p>
<p>Vollkommen unrelated mit dem oben geposteten Code, sorry. Manchmal ist der Fehler eben nicht da, wo er sich zeigt.<br />
Würde jetzt zu weit führen, zu erklären, was passiert ist, nur so viel:</p>
<p>Gefunden habe ich den Fehler gerade durch Cookie-Debugging: Rechner zugeklappt, in die Teeküche gegangen, Tee gekocht, Keks gegessen, nachgedacht, &quot;Aha!&quot;-Erlebnis gehabt. Rechner aufgeklappt, probiert, funktioniert.<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>
<p>Phil</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1909511</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1909511</guid><dc:creator><![CDATA[PhilippM]]></dc:creator><pubDate>Wed, 09 Jun 2010 14:20:38 GMT</pubDate></item></channel></rss>