<?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[Container mit lazy subsets: wie Veränderung erkennen?]]></title><description><![CDATA[<p>Hallo,</p>
<p>Für unser Projekt bastlen wir gerade an einem Container mit besonderen Anforderungen: gespeichert werden sehr viele, zum Teil große Daten (Zum Beispiel eine Menge von Bildsequenzen). Von diesen Containern sollen subsets gebildet werden können. In unserer jetzigen Implementation verwenden wir dazu einfache indexsets, die das Subset erzeugen. Das Haupset besitzt also einen kompletten Satz indizes und alle subsets (und subsets dieser subsets) eine Untermenge. Dies soll so lange gelten, bis entweder die Eltern oder die Kinder verädnert werden. In dem Fall sollen die Daten kopiert werden, damit Veränderungen des einen Subsets nicht die Eltern oder Geschwister verändern.</p>
<p>Nun haben wir das Folgende Problem:</p>
<pre><code class="language-cpp">Container&lt;Bar&gt; parent(...);
std::generate(parent.begin(),parent.end(),foo);//Daten erzeugen a)
Container&lt;Bar&gt; child;
std::vector&lt;unsigned int&gt; indizes;
parent.createSubset(indizes,child);//lazy subset! alle Daten referenzieren direkt auf parent

//ausgeben des subsets b)
foreach(Bar&amp; v, child)
    std::cout&lt;&lt;v&lt;&lt;std::endl;

//in place transformation c)
std::transform(child.begin(),child.end(),child.begin(),fooBar);
</code></pre>
<p>Die Container sollen STL conform sein, also wenn die STL algorithmen benutzt werden sollen, soll das gehen a). Hier ist das auch kein Problem, weil noch keine Kidner da sind und ich nicht darauf achten muss, sie zu ändern.<br />
Auch b) soll gehen, und zwar ohne dass das subset kopiert wird. Es besteht ja kein Grund dafür. Aber wie kann ich b) von c) unterscheiden?</p>
<p>Hat jemand eine Lösung dafür? Ich tendiere momentan zu: das geht nicht. Kann man das Design irgendwie sinnvoll abändern, dass ich möglichst wenige Einschränkungen habe und trotzdem keine 1000 programmierer mir die Bude einrnenen, weil sie sich ihre Daten zerschossen haben?</p>
<p>Ich überlege mir, ob ich Subsets nicht doch einen anderen Datentyp gebe. Dann kann ich sagen, dass sie immer nur konstante Referenzen zurückgeben. Will der Benutzer dann eine Datentransformation machen, kann er sie einfach mit transform in einen anderen Container schieben. Allerdings würde das zusätzliche Klassen bedeuten...</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/289199/container-mit-lazy-subsets-wie-veränderung-erkennen</link><generator>RSS for Node</generator><lastBuildDate>Wed, 19 Aug 2026 08:53:10 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/289199.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 29 Jun 2011 22:06:49 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Container mit lazy subsets: wie Veränderung erkennen? on Wed, 29 Jun 2011 22:06:49 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>Für unser Projekt bastlen wir gerade an einem Container mit besonderen Anforderungen: gespeichert werden sehr viele, zum Teil große Daten (Zum Beispiel eine Menge von Bildsequenzen). Von diesen Containern sollen subsets gebildet werden können. In unserer jetzigen Implementation verwenden wir dazu einfache indexsets, die das Subset erzeugen. Das Haupset besitzt also einen kompletten Satz indizes und alle subsets (und subsets dieser subsets) eine Untermenge. Dies soll so lange gelten, bis entweder die Eltern oder die Kinder verädnert werden. In dem Fall sollen die Daten kopiert werden, damit Veränderungen des einen Subsets nicht die Eltern oder Geschwister verändern.</p>
<p>Nun haben wir das Folgende Problem:</p>
<pre><code class="language-cpp">Container&lt;Bar&gt; parent(...);
std::generate(parent.begin(),parent.end(),foo);//Daten erzeugen a)
Container&lt;Bar&gt; child;
std::vector&lt;unsigned int&gt; indizes;
parent.createSubset(indizes,child);//lazy subset! alle Daten referenzieren direkt auf parent

//ausgeben des subsets b)
foreach(Bar&amp; v, child)
    std::cout&lt;&lt;v&lt;&lt;std::endl;

//in place transformation c)
std::transform(child.begin(),child.end(),child.begin(),fooBar);
</code></pre>
<p>Die Container sollen STL conform sein, also wenn die STL algorithmen benutzt werden sollen, soll das gehen a). Hier ist das auch kein Problem, weil noch keine Kidner da sind und ich nicht darauf achten muss, sie zu ändern.<br />
Auch b) soll gehen, und zwar ohne dass das subset kopiert wird. Es besteht ja kein Grund dafür. Aber wie kann ich b) von c) unterscheiden?</p>
<p>Hat jemand eine Lösung dafür? Ich tendiere momentan zu: das geht nicht. Kann man das Design irgendwie sinnvoll abändern, dass ich möglichst wenige Einschränkungen habe und trotzdem keine 1000 programmierer mir die Bude einrnenen, weil sie sich ihre Daten zerschossen haben?</p>
<p>Ich überlege mir, ob ich Subsets nicht doch einen anderen Datentyp gebe. Dann kann ich sagen, dass sie immer nur konstante Referenzen zurückgeben. Will der Benutzer dann eine Datentransformation machen, kann er sie einfach mit transform in einen anderen Container schieben. Allerdings würde das zusätzliche Klassen bedeuten...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2086346</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2086346</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Wed, 29 Jun 2011 22:06:49 GMT</pubDate></item><item><title><![CDATA[Reply to Container mit lazy subsets: wie Veränderung erkennen? on Wed, 29 Jun 2011 22:19:35 GMT]]></title><description><![CDATA[<p>Entweder merken die Bars, dass sie geändert werden oder die Iteratoren geben nur Proxys zurück. Bei letzteren wärst du nicht vor direkten Zugriffen auf die einzelnen Elemente des Containers geschützt.</p>
<p>Würde es sich lohnen, bei Änderungen an einem Objekt wirklich nur dieses eine Objekt zu duplizieren und zu ändern? Die Referenzen auf die anderen Objekte des Parents könnten bestehen bleiben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2086355</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2086355</guid><dc:creator><![CDATA[Michael E.]]></dc:creator><pubDate>Wed, 29 Jun 2011 22:19:35 GMT</pubDate></item><item><title><![CDATA[Reply to Container mit lazy subsets: wie Veränderung erkennen? on Wed, 29 Jun 2011 22:23:20 GMT]]></title><description><![CDATA[<p>Ein Ansatz wäre es, wenn die Container-Iteratoren etwas zurückliefern, was sich wie eine Element-Referenz verhält, aber bei Schreibversuchen dazwischengreifen kann:</p>
<pre><code class="language-cpp">class reference
{
private:
  Container&amp; basis;
  ...
  reference(Container&amp; b,/*...*/);
  void check_container();//nötige Maßnahmen für die Copy-On-Write Behandlung
public:
  operator const T&amp;() const;
  //wenn ein neuer Wert zugewiesen wird, mußt du auf jeden Fall eine Kopie anlegen:
  reference operator=(const T&amp;)
  {
    check_container();
    ...
  }
  ...
};

class iterator
{
  ...
public:
  T operator*() const;
  reference operator*();
  ...
};
</code></pre>
<p>(nur grob aus dem Gedächtnis zusammengezimmert)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2086358</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2086358</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Wed, 29 Jun 2011 22:23:20 GMT</pubDate></item><item><title><![CDATA[Reply to Container mit lazy subsets: wie Veränderung erkennen? on Wed, 29 Jun 2011 22:39:51 GMT]]></title><description><![CDATA[<p>Proxys funktioneiren leider nicht, weil die Bar keine einfachen Datentypen sind, bzw frei wählbar. Wenn ich also sowas mache wie</p>
<pre><code class="language-cpp">child.begin()-&gt;changeThis();
</code></pre>
<p>Dann kriege ich das wieder nicht mit. Aber Danke für deinen Ansatz.</p>
<blockquote>
<p>Würde es sich lohnen, bei Änderungen an einem Objekt wirklich nur dieses eine Objekt zu duplizieren und zu ändern?</p>
</blockquote>
<p>Nein, wahrscheinlich nicht. Meistens wird direkt das ganze Set verädnert. Deswegne konnten wir vorher</p>
<pre><code class="language-cpp">child.transform(fooBar);
</code></pre>
<p>bzw haben eine Methode, die das Set unabhängig von den anderen macht. Aber zusammen mit dem STL-Algorithmen ist das alles viel zu fehleranfällig - auch wnen ich normalerweise den Programmierer nicht vor ihm selbst retten will, da sist einfach zu unintuitiv.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2086362</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2086362</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Wed, 29 Jun 2011 22:39:51 GMT</pubDate></item><item><title><![CDATA[Reply to Container mit lazy subsets: wie Veränderung erkennen? on Wed, 29 Jun 2011 22:54:18 GMT]]></title><description><![CDATA[<p>otze schrieb:</p>
<blockquote>
<p>Proxys funktioneiren leider nicht, weil die Bar keine einfachen Datentypen sind, bzw frei wählbar. Wenn ich also sowas mache wie</p>
<pre><code class="language-cpp">child.begin()-&gt;changeThis();
</code></pre>
<p>Dann kriege ich das wieder nicht mit. Aber Danke für deinen Ansatz.</p>
</blockquote>
<p>Die -&gt; Operatoren deines Iterators kannst du auch überladen. Und im Ernstfall mußt du vermutlich ohnehin pessimistisch an die Sache herangehen - wenn du nicht feststellen kannst, ob ein Aufruf das darunterliegende Set ändert, dann gehst du lieber davon aus daß er es tut.<br />
(da hat man lieber eine eigentlich nicht benötigte Kopie als ein Aliasing, das den gesamten Programmablauf kaputtmacht)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2086367</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2086367</guid><dc:creator><![CDATA[CStoll]]></dc:creator><pubDate>Wed, 29 Jun 2011 22:54:18 GMT</pubDate></item><item><title><![CDATA[Reply to Container mit lazy subsets: wie Veränderung erkennen? on Thu, 30 Jun 2011 09:05:16 GMT]]></title><description><![CDATA[<p>Was wären denn alternativen im Design?</p>
<p>Momentan schaue ich, ob sowas funktionieren könnte:</p>
<pre><code class="language-cpp">//nur skizziert
//die Klasse erledigt die komplette Speicherverwaltung und subseterzeugung. 
//Die davon
//abgeleiteten Klassen überschreiben nur kleine Dinge
template&lt;class T&gt;
class ImmutableContainer{
public:
   const T* begin()const;
   const T* end()const;
   const T* begin();//immutable
   const T* end();//immutable

};
template&lt;class T&gt;
class ContainerView: public ImmutableContainer&lt;T&gt;{
    //...
};
template&lt;class T&gt;
class Container: public ImmutableContainer&lt;T&gt;{
     //erzeugt deep copy
     explizit Container(const ImmutableContainer&lt;T&gt;&amp;);
     const Container&amp; operator=(const ImmutableContainer&lt;T&gt;&amp;);
     //...
     //explizite überladung, da der Container AUCH mutable ist
     T* begin();
     T* end();
};

//Nun Anwendung

template&lt;class T&gt;
void printContainer(const ImmutableContainer&lt;T&gt;&amp;){
    foreach(Bar&amp; v, child)
        std::cout&lt;&lt;v&lt;&lt;std::endl;
}

Container&lt;Bar&gt; parent(...);
std::generate(parent.begin(),parent.end(),foo);//klappt

ContainerView&lt;Bar&gt; child;//anderer Typ für subsets
std::vector&lt;unsigned int&gt; indizes;
parent.createSubset(indizes,child);

printContainer(parent);//klappt
printContainer(child);//dito

std::transform(child.begin(),child.end(),child.begin(),fooBar); //verboten
Container&lt;Bar&gt; copyChild(...);
std::transform(child.begin(),child.end(),copyChild.begin(),fooBar); //klappt!
copyChild = child;
std::transform(copyChild.begin(),copyChild.end(),copyChild.begin(),fooBar); //klappt!
</code></pre>
<p>Das einzige Problem wa sjetzt noch bleibt ist, wenn jemand nach erzeugen von child den parent verändert. Aber das wird wohl nicht passieren.</p>
<p>Anregungen?</p>
<p>//edit eventuell könnte ich ImmutableContainer weg lassen und dafür Container von ContainerView ableiten. spart eine Basisklasse. Und ist vielleicht semantisch angenehmer.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2086470</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2086470</guid><dc:creator><![CDATA[otze]]></dc:creator><pubDate>Thu, 30 Jun 2011 09:05:16 GMT</pubDate></item></channel></rss>