<?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[Memento mit Originator drumherum oder für sich?]]></title><description><![CDATA[<p>Hi,</p>
<p>ich möchte jetzt ein Memento-Pattern einbauen. Normalerweise heißt es ja, dass das Memento selbst nicht für Erstellung/Wiederherstellung zuständig sein soll, sondern nur den State widerspiegelt. Hat das einen tieferen Sinn?</p>
<p>Ich hätte es jetzt so gebastelt:</p>
<pre><code class="language-cpp">class Object; // das soll gespeichert werden

class Mememento
{
public:
   Memento(const Object&amp; obj); // das hier erstellt das Memento einfach

   void Restore(Object&amp; obj); // das stellt das Objekt wieder her

private:
   // der State wird hier irgendwie abgebildet 
};
</code></pre>
<p>Nach den üblichen verdächtigen Quellen würde man hier eine Originator-Klasse drumbasteln (bzw. hier würde ich einfach freie Funktionen, evtl. mit namespace nutzen) und darin das Memento hauen, das dann aber einer einfachen Datenstruktur entspricht, die jetzt keine wirklichen Methoden hat (Setter/Getter, dann kann das aber auch einfach eine struct sein).</p>
<p>Das wäre also etwa so was:</p>
<pre><code class="language-cpp">namespace Originator
{
    struct Memento
    {
        // state
    }

    Memento createMemento(const Object&amp; obj);
    void restoreFromMemento(Object&amp; obj);
};
</code></pre>
<p>Frage 1: Ich sehe darin jedoch keinen Vorteil. Gibt es einen?</p>
<p>Frage 2:<br />
Ich will eigentlich lieber:</p>
<pre><code class="language-cpp">Object Restore();
</code></pre>
<p>haben, aber Object ist non-copyable, jedoch moveable. Das sollte theoretisch ja reichen. Ein temporäres Objekt darf ich aber nicht moven, sodass</p>
<pre><code class="language-cpp">Object&amp;&amp; Restore();
</code></pre>
<p>nicht geht.</p>
<p>Bei</p>
<pre><code class="language-cpp">Object Restore();
</code></pre>
<p>bin ich aber darauf angewiesen, dass der NRVO korrekt anwendet, oder? Ist irgendwie doof sich darauf zu verlassen (oder ist das hier garantiert, weil es nicht mehr NRVO heißt?). Muss ich ansonsten zwangsläufig einen Umweg über ein Objekt wie:</p>
<pre><code class="language-cpp">class Restorer
{
public:
    Restorer(const&amp; Memento memento); // erstellt temp
    Object&amp;&amp; Restore()&amp;&amp; {return std::move(temp);}

private:
    Object temp;
};
</code></pre>
<p>gehen, wobei in</p>
<pre><code class="language-cpp">Object obj = std::move(Restorer(memento)).Restore();
</code></pre>
<p>das temporäre Objekt ja die Anweisung überlebt, sodass das Verhalten wohldefiniert ist?</p>
<p>Beste Grüße,<br />
Eisflamme</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/320500/memento-mit-originator-drumherum-oder-für-sich</link><generator>RSS for Node</generator><lastBuildDate>Fri, 24 Jul 2026 02:40:32 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/320500.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 30 Sep 2013 13:32:27 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Memento mit Originator drumherum oder für sich? on Mon, 30 Sep 2013 14:13:50 GMT]]></title><description><![CDATA[<p>Hi,</p>
<p>ich möchte jetzt ein Memento-Pattern einbauen. Normalerweise heißt es ja, dass das Memento selbst nicht für Erstellung/Wiederherstellung zuständig sein soll, sondern nur den State widerspiegelt. Hat das einen tieferen Sinn?</p>
<p>Ich hätte es jetzt so gebastelt:</p>
<pre><code class="language-cpp">class Object; // das soll gespeichert werden

class Mememento
{
public:
   Memento(const Object&amp; obj); // das hier erstellt das Memento einfach

   void Restore(Object&amp; obj); // das stellt das Objekt wieder her

private:
   // der State wird hier irgendwie abgebildet 
};
</code></pre>
<p>Nach den üblichen verdächtigen Quellen würde man hier eine Originator-Klasse drumbasteln (bzw. hier würde ich einfach freie Funktionen, evtl. mit namespace nutzen) und darin das Memento hauen, das dann aber einer einfachen Datenstruktur entspricht, die jetzt keine wirklichen Methoden hat (Setter/Getter, dann kann das aber auch einfach eine struct sein).</p>
<p>Das wäre also etwa so was:</p>
<pre><code class="language-cpp">namespace Originator
{
    struct Memento
    {
        // state
    }

    Memento createMemento(const Object&amp; obj);
    void restoreFromMemento(Object&amp; obj);
};
</code></pre>
<p>Frage 1: Ich sehe darin jedoch keinen Vorteil. Gibt es einen?</p>
<p>Frage 2:<br />
Ich will eigentlich lieber:</p>
<pre><code class="language-cpp">Object Restore();
</code></pre>
<p>haben, aber Object ist non-copyable, jedoch moveable. Das sollte theoretisch ja reichen. Ein temporäres Objekt darf ich aber nicht moven, sodass</p>
<pre><code class="language-cpp">Object&amp;&amp; Restore();
</code></pre>
<p>nicht geht.</p>
<p>Bei</p>
<pre><code class="language-cpp">Object Restore();
</code></pre>
<p>bin ich aber darauf angewiesen, dass der NRVO korrekt anwendet, oder? Ist irgendwie doof sich darauf zu verlassen (oder ist das hier garantiert, weil es nicht mehr NRVO heißt?). Muss ich ansonsten zwangsläufig einen Umweg über ein Objekt wie:</p>
<pre><code class="language-cpp">class Restorer
{
public:
    Restorer(const&amp; Memento memento); // erstellt temp
    Object&amp;&amp; Restore()&amp;&amp; {return std::move(temp);}

private:
    Object temp;
};
</code></pre>
<p>gehen, wobei in</p>
<pre><code class="language-cpp">Object obj = std::move(Restorer(memento)).Restore();
</code></pre>
<p>das temporäre Objekt ja die Anweisung überlebt, sodass das Verhalten wohldefiniert ist?</p>
<p>Beste Grüße,<br />
Eisflamme</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2356758</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2356758</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 30 Sep 2013 14:13:50 GMT</pubDate></item><item><title><![CDATA[Reply to Memento mit Originator drumherum oder für sich? on Mon, 30 Sep 2013 14:21:30 GMT]]></title><description><![CDATA[<blockquote>
<p>dass das Memento selbst nicht für Erstellung/Wiederherstellung zuständig sein soll</p>
</blockquote>
<p>Dazu muesste es hoechstwahrscheinlich auf private Member zugreifen.</p>
<blockquote>
<p>Originator-Klasse drumbasteln</p>
</blockquote>
<p>Ist das Objekt dessen Zustand gespeichert werden soll.</p>
<pre><code class="language-cpp">Memento createMemento(const Object&amp; obj);
    void restoreFromMemento(Object&amp; obj);
</code></pre>
<p>Muss wahrscheilich auf private Daten von Object zufgreifen.</p>
<p>Warum willst du moven? Memento speichert den Zustand fuer spaeter, d.h. eine Weiterbenutzung des eigentlichen Objekts sollte nichts im Weg stehen. Wird es verschoben, kann es vielleicht nicht mehr so benutzt werden, wie ohne Verschiebung.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2356771</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2356771</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Mon, 30 Sep 2013 14:21:30 GMT</pubDate></item><item><title><![CDATA[Reply to Memento mit Originator drumherum oder für sich? on Mon, 30 Sep 2013 14:23:53 GMT]]></title><description><![CDATA[<p>Du hast Recht, danke! Ich hatte gedacht, Originator wäre ein weiteres Objekt (oder namespace).</p>
<p>Wenn Originator == Object, dann kann Object einfach alles übernehmen, irgendwie hatte ich kurz den Gedanken, dass es doch toll wäre die Erstellung/Wiederherstellung aus Object herauszulösen... ohne mir jetzt erkennbare Vorteile.</p>
<p>Wenn ich aber eine freie Funktion habe, die Object zurückgibt, dann würde er ohne NRVO kopieren. Wenn Object nicht copyable ist, geht das aber nicht, also &quot;müsste&quot; ich das temporär erstellte Objekt moven, was natürlich nicht geht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2356774</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2356774</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 30 Sep 2013 14:23:53 GMT</pubDate></item><item><title><![CDATA[Reply to Memento mit Originator drumherum oder für sich? on Mon, 30 Sep 2013 14:26:09 GMT]]></title><description><![CDATA[<blockquote>
<p>Wenn ich aber eine freie Funktion habe, die Object zurückgibt, dann würde er ohne NRVO kopieren. Wenn Object nicht copyable ist, geht das aber nicht, also &quot;müsste&quot; ich das temporär erstellte Objekt moven, was natürlich nicht geht.</p>
</blockquote>
<p>Das sind doch alles nur Randueberlegungen. premature</p>
<p>Memento ist nur eine etwas eigene Form der Serialisierung. Hier wird eben keine datei oder aehnliches benutzt sondern ein Objekt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2356776</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2356776</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Mon, 30 Sep 2013 14:26:09 GMT</pubDate></item><item><title><![CDATA[Reply to Memento mit Originator drumherum oder für sich? on Mon, 30 Sep 2013 14:26:11 GMT]]></title><description><![CDATA[<p>Da ich es jetzt eh mit Originator == Object umsetze, ist es auch einfach egal.</p>
<p>Wenn ich es aber mit freier Funktion machen würde, warum wäre es dann premature? Du meinst, ich sollte einfach:</p>
<pre><code class="language-cpp">Object create(const Memento&amp; m)
{
    Object obj(/* ... */);
    // tu was
    return obj;
}
</code></pre>
<p>schreiben und hoffen, dass der Compiler das schon von selbst moved?</p>
<p>Ist halt blöd, wenn mein Compiler das zufällig macht, ein anderer aber nicht, darum wollte ich das vorher diskutiert haben, um nicht compilerabhängigen Code zu schreiben. <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/2356777</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2356777</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 30 Sep 2013 14:26:11 GMT</pubDate></item><item><title><![CDATA[Reply to Memento mit Originator drumherum oder für sich? on Mon, 30 Sep 2013 14:31:44 GMT]]></title><description><![CDATA[<blockquote>
<p>schreiben und hoffen, dass der Compiler das schon von selbst moved?</p>
</blockquote>
<p>Das ist erstmal NRVO. Und wenn du <code>Object obj = std::move(create(...))</code> machst, dann sollte der move-Konstruktor aufgerufen werden.</p>
<p>Ich verstehe nicht, warum create/restore eine freie Funktion sein soll. Und da es hauptsaechlich um das zuruecksetzen in einen vorherigen Zustand geht, sollte die Klasse es explizit im Interface formulieren. Aehnlich wie bei Serialisierung, nur die Klasse Weiss, wie Objekte de-/serialisiert werden koennen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2356779</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2356779</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Mon, 30 Sep 2013 14:31:44 GMT</pubDate></item><item><title><![CDATA[Reply to Memento mit Originator drumherum oder für sich? on Mon, 30 Sep 2013 14:34:05 GMT]]></title><description><![CDATA[<p>Ahhhh, natürlich. Alles klar, dankeschön <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="👍"
    /></p>
<p>Und wie gesagt, das mit der freien Funktion war falsch von mir gedacht, weil mein Gedankengang war: Man braucht Originator mit Originator != Object (das war falsch) und da ich Originator dann aber nicht als Klasse, sondern eher namespace sah, wurden die restore/create-Funktionen automatisch zu freien Funktionen.</p>
<p>War Käse, werden jetzt Methoden von Object, wie Du ja vorgeschlagen hast. <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/2356781</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2356781</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 30 Sep 2013 14:34:05 GMT</pubDate></item><item><title><![CDATA[Reply to Memento mit Originator drumherum oder für sich? on Mon, 30 Sep 2013 14:32:57 GMT]]></title><description><![CDATA[<blockquote>
<p>Und wenn du Object obj = std::move(create(...)) machst, dann sollte der move-Konstruktor aufgerufen werden.</p>
</blockquote>
<p>Da braucht es kein <code>move</code> . Solange <code>create(...)</code> ein rvalue ist (was bei obiger Definition der Fall ist), dann wird automatisch der Move-Konstruktor gewählt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2356782</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2356782</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Mon, 30 Sep 2013 14:32:57 GMT</pubDate></item><item><title><![CDATA[Reply to Memento mit Originator drumherum oder für sich? on Mon, 30 Sep 2013 14:33:30 GMT]]></title><description><![CDATA[<p>Sone:<br />
Gut zu wissen, danke für die Ergänzung!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2356783</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2356783</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 30 Sep 2013 14:33:30 GMT</pubDate></item><item><title><![CDATA[Reply to Memento mit Originator drumherum oder für sich? on Mon, 30 Sep 2013 14:41:02 GMT]]></title><description><![CDATA[<p>Ich habe das Eingangsposting nur flüchtig gelesen. Wenn's aber um Versionierung und/oder Undo/Redo geht, sollte man sich vielleicht mal überlegen, ob einem Copy-on-Write helfen könnte. Dann würde man einfach die alte Version behalten, kopieren und die Kopie ändern. Per COW und geschickten Baum-artigek Strukturen könnte man viel Redundanz einsparen. Sean Parent, einer von Adobe, hatte dazu mal einen Vortrag gemacht. So haben die in ihrer neuen Photoshop-Version das Undo/Redo-System gemacht. Sei wohl alles weniger fehleranfällig und leichter durchschaubar als das, was sie vorher hatten.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2356789</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2356789</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Mon, 30 Sep 2013 14:41:02 GMT</pubDate></item><item><title><![CDATA[Reply to Memento mit Originator drumherum oder für sich? on Mon, 30 Sep 2013 14:46:55 GMT]]></title><description><![CDATA[<p>Es geht in der Tat um Undo/Redo und zwar von baumartigen Strukturen.</p>
<p>Für jetzt reicht zwar mein einfaches System (auch wenn es durch Kopien langsam für riesige Datenmengen ist, die zum Glück aber eh nicht praktikabel sind), aber besser ist immer gut.</p>
<p>Auf die (sehr) Schnelle hat mein googlen nichts ergeben. Hast Du rasch einen Link oder das richtige Stichwort parat? Falls das in eine Suche Deinerseits ausarten würde, mache ich das natürlich selbst.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2356791</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2356791</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Mon, 30 Sep 2013 14:46:55 GMT</pubDate></item><item><title><![CDATA[Reply to Memento mit Originator drumherum oder für sich? on Mon, 30 Sep 2013 15:03:57 GMT]]></title><description><![CDATA[<p>Einer von den aktuellen Going Native 2013 Videos.</p>
<p>Und wenn es um Baumstrukturen geht, sind <a href="http://en.wikipedia.org/wiki/Persistent_data_structure" rel="nofollow">http://en.wikipedia.org/wiki/Persistent_data_structure</a> ganz gut.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2356798</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2356798</guid><dc:creator><![CDATA[knivil]]></dc:creator><pubDate>Mon, 30 Sep 2013 15:03:57 GMT</pubDate></item><item><title><![CDATA[Reply to Memento mit Originator drumherum oder für sich? on Wed, 02 Oct 2013 07:43:38 GMT]]></title><description><![CDATA[<p>Der Vortrag, den ichmeinte, ist älter:</p>
<p><a href="http://isocpp.org/blog/2012/12/value-semantics-and-concepts-based-polymorphism-sean-parent" rel="nofollow">http://isocpp.org/blog/2012/12/value-semantics-and-concepts-based-polymorphism-sean-parent</a></p>
<p>Leider ist die Qualität des Videos nicht so dolle.</p>
<p>In seinen neueren Going Native 2013 Talks gibt es Parallelen, die haben aber weniger was mit Undo/Redo zu tun.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2357242</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2357242</guid><dc:creator><![CDATA[krümelkacker]]></dc:creator><pubDate>Wed, 02 Oct 2013 07:43:38 GMT</pubDate></item><item><title><![CDATA[Reply to Memento mit Originator drumherum oder für sich? on Wed, 02 Oct 2013 09:16:22 GMT]]></title><description><![CDATA[<p>Habe mir den Vortrag durchgeschaut, das undo/redo ist da aber nur ein Nebenresultat, finde ich. Das ist zwar cool, aber zentral ist ja das Nutzen von Baumstrukturen, auf deren Elemente man Operationen anwenden kann, die nur für den notwendigen Fall polymorph sind. (hm, aber die Zusammenfassung erscheint mir nicht so passend; value-semantics aber auch nicht) Die Idee, dass Polymorphie nur Implementierungsdetail ist und nicht den Client-Code verkomplizieren soll, finde ich am spannendsten (das wurde hier ja auch bereits von einigen angemerkt, erscheint mir aber noch eine wenig durchgesetzte Idee).</p>
<p>Auf alle Fälle interessante Ideen drin. <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>Leider sind meine Baumstrukturen relativ komplex, sodass es eigentlich Sinn ergeben würde, dass ich nur die Änderungen speichere. Aber es reicht von der Performance gerade noch aus.</p>
<p>knivil:<br />
Danke auch dafür, da schaue ich dann als nächstes rein. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f60b.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_savoring_food"
      title=":yum:"
      alt="😋"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2357250</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2357250</guid><dc:creator><![CDATA[Eisflamme]]></dc:creator><pubDate>Wed, 02 Oct 2013 09:16:22 GMT</pubDate></item></channel></rss>