<?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[Ableitung durch Policy ersetzen]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich habe ein Design mit einer abstrakten Basisklasse und zwei konkreten Unterklassen. Es ist aber so, dass ein Programm immer nur eine Unterklasse benutzt, abhängig davon wie es kompiliert ist. Also es kann zur Laufzeit nie sein, dass die andere Unterklasse benutzt wird. Daher ist es ziemlich sinnfrei, die virtuellen Funktionen mit mir herumzuschleppen, man könnte das stattdessen schon zur Kompilierzeit entscheiden. Daher möchte ich die konkrete Funktionalität der Unterklasse durch Policies realisieren.</p>
<p>Der Ist-Zustand mal konkret in Code ausgedrückt:</p>
<pre><code class="language-cpp">template &lt;typename T, typename U = T&gt;
class Base {
public:
    Base (int whatever):
    m_whatever(whatever)
    {}

    virtual ~Base() { /* machs kaputt */ }

    virtual void foo(const T&amp; t) = 0;

protected:
    int m_whatever
    // weitere Membervariablen, die von U und T abhängen, weggelassen
};

template &lt;typename U, typename U = T&gt;
class ConcreteA : public Base&lt;U,T&gt; {
public:
    ConcreteA(const std::string&amp; bar, int whatever):
    Base(whatever),
    m_bar(bar)
    {}

    void foo(const T&amp; t) { doSomething(t, this-&gt;whatever, m_bar); }   

private:
   std::string m_bar;
}

template &lt;typename U, typename U = T&gt;
class ConcreteB : public Base&lt;U,T&gt; {
public:
    ConcreteB(float baz, int whatever):
    Base(whatever),
    m_baz(baz)
    {}

    void foo(const T&amp; t) { doSomethingElse(t, this-&gt;whatever, m_baz); }   

private:
   float m_baz
}

// irgendwo anders
boost::ptr_vector&lt;Base&lt;int&gt; &gt; vector_of_stuff;
#ifdef USE_A
while(noch_daten_in_config_datei()) {
    std::string a_string = lese_string_aus_config_datei();
    vector_of_stuff.push_back(new ConcreteA(a_string, 4711);
}
#else
while(noch_daten_in_config_datei()) {
    float b_float = lese_float_aus_config_datei();
    vector_of_stuff.push_back(new ConcreteB(b_float, 4711);
}
#endif

vector_of_stuff[23]-&gt;foo(42);
</code></pre>
<p>Das mit dem ifdef ist jetzt etwas übertrieben, aber im Grunde ist es genau so, dass sich schon zur Compile-Zeit entscheidet, dass vector_of_stuff nur außschließlich ConcreteAs oder ConcreteBs enthalten wird, nie aber beide gemischt.</p>
<p>Daher ist es relativ sinnfrei, hier öffentliche Vererbung zu benutzen und bei jedem Aufruf von foo eine virtuelle Funktion zu dereferenzieren. Sinnvoller wäre, zur Compilezeit über Policies fetzulegen, was bei foo() gemacht werden soll.</p>
<p>Der erste Ansatz dahingehend ist:</p>
<pre><code class="language-cpp">template &lt;typename FooPolicy, typename T, typename U = T&gt;
class Base : public FooPolicy{
public:
    using FooPolicy::doFoo;

    Base (int whatever):
    m_whatever(whatever)
    {}

    ~Base() { /* machs kaputt */ }

    void foo(const T&amp; t) { doFoo(t); }

protected:
    int m_whatever
    // weitere Membervariablen, die von U und T abhängen, weggelassen
};

template &lt;typename U, typename U = T&gt;
class APolicy {
public:
    APolicy(const std::string&amp; bar, Base&lt;U,T&gt;&amp; base):
    m_base(base),
    m_bar(bar)
    {}

    void doFoo(const T&amp; t) { doSomething(t, m_base-&gt;whatever, m_bar); }   

private:
   std::string m_bar;
}

template &lt;typename U, typename U = T&gt;
class BPolicy {
public:
    BPolicy(float baz, Base&lt;U,T&gt;&amp; base):
    m_base(base),
    m_baz(baz)
    {}

    void doFoo(const T&amp; t) { doSomethingElse(t, m_base-&gt;whatever, m_baz); }   

private:
   float m_baz
}

// irgendwo anders
std::vector&lt;Base&lt;A_Policy, int&gt; &gt; vector_of_stuff;

vector_of_stuff[23].foo(42);
</code></pre>
<p>Dabei habe ich im Grunde zwei Probleme: Erstens, der Zugriff auf die in Base gespeicherten Daten. Dazu müsste ich zunächsts einmal die Policies zu &quot;friends&quot; von Base machen, damit sie m_whatever benutzen können. Das ist ja nicht weiter schlimm. Aber auf Ojektebene müssen sie ihr Base-Objekt ja auch kennen, daher der Konstruktor mit Base&amp; base.</p>
<p>Wie aber sieht jetzt der Base-Konstruktor aus?<br />
Angenommen, Base besitzt ein Objekt der Policy, dann müssten die Base-Konstruktoren ja so aussehen:</p>
<pre><code class="language-cpp">Base (const std::string&amp; bar, int whatever):
policy(*this, bar),
m_whatever(whatever)

Base (float baz, int whatever):
policy(*this, baz),
m_whatever(whatever)
</code></pre>
<p>Das ist aber in zweifacher Hinsicht Blödsinn, denn erstens kompiliert es nicht, da es ja immer nur einen Policy-Konstruktor gibt, der ENTWEDER einen String ODER ein float annimmt, jenachdem welche Policy man benutzt,<br />
und zweitens ist mir nicht wohl dabei, in der Initialisierungsliste des Konstruktors den this-Pointer zu dereferenzieren und an jemanden weiterzugeben. Im this-Pointer steht zu dem Zeitpunkt doch wahrscheinlich noch bit-Müll, oder?</p>
<p>Okay, ich hoffe ich habe das Problem verständlich dargestellt.<br />
Die Grundfrage ist also: wie refaktorisiert man abgeleitete Klassen in Policies, wenn sie Daten der Basisklasse benutzen UND subtil unterschiedliche Konstruktoren haben?</p>
<p>Philipp</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/275817/ableitung-durch-policy-ersetzen</link><generator>RSS for Node</generator><lastBuildDate>Wed, 26 Aug 2026 16:16:34 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/275817.rss" rel="self" type="application/rss+xml"/><pubDate>Thu, 21 Oct 2010 13:40:18 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Ableitung durch Policy ersetzen on Thu, 21 Oct 2010 13:40:18 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>ich habe ein Design mit einer abstrakten Basisklasse und zwei konkreten Unterklassen. Es ist aber so, dass ein Programm immer nur eine Unterklasse benutzt, abhängig davon wie es kompiliert ist. Also es kann zur Laufzeit nie sein, dass die andere Unterklasse benutzt wird. Daher ist es ziemlich sinnfrei, die virtuellen Funktionen mit mir herumzuschleppen, man könnte das stattdessen schon zur Kompilierzeit entscheiden. Daher möchte ich die konkrete Funktionalität der Unterklasse durch Policies realisieren.</p>
<p>Der Ist-Zustand mal konkret in Code ausgedrückt:</p>
<pre><code class="language-cpp">template &lt;typename T, typename U = T&gt;
class Base {
public:
    Base (int whatever):
    m_whatever(whatever)
    {}

    virtual ~Base() { /* machs kaputt */ }

    virtual void foo(const T&amp; t) = 0;

protected:
    int m_whatever
    // weitere Membervariablen, die von U und T abhängen, weggelassen
};

template &lt;typename U, typename U = T&gt;
class ConcreteA : public Base&lt;U,T&gt; {
public:
    ConcreteA(const std::string&amp; bar, int whatever):
    Base(whatever),
    m_bar(bar)
    {}

    void foo(const T&amp; t) { doSomething(t, this-&gt;whatever, m_bar); }   

private:
   std::string m_bar;
}

template &lt;typename U, typename U = T&gt;
class ConcreteB : public Base&lt;U,T&gt; {
public:
    ConcreteB(float baz, int whatever):
    Base(whatever),
    m_baz(baz)
    {}

    void foo(const T&amp; t) { doSomethingElse(t, this-&gt;whatever, m_baz); }   

private:
   float m_baz
}

// irgendwo anders
boost::ptr_vector&lt;Base&lt;int&gt; &gt; vector_of_stuff;
#ifdef USE_A
while(noch_daten_in_config_datei()) {
    std::string a_string = lese_string_aus_config_datei();
    vector_of_stuff.push_back(new ConcreteA(a_string, 4711);
}
#else
while(noch_daten_in_config_datei()) {
    float b_float = lese_float_aus_config_datei();
    vector_of_stuff.push_back(new ConcreteB(b_float, 4711);
}
#endif

vector_of_stuff[23]-&gt;foo(42);
</code></pre>
<p>Das mit dem ifdef ist jetzt etwas übertrieben, aber im Grunde ist es genau so, dass sich schon zur Compile-Zeit entscheidet, dass vector_of_stuff nur außschließlich ConcreteAs oder ConcreteBs enthalten wird, nie aber beide gemischt.</p>
<p>Daher ist es relativ sinnfrei, hier öffentliche Vererbung zu benutzen und bei jedem Aufruf von foo eine virtuelle Funktion zu dereferenzieren. Sinnvoller wäre, zur Compilezeit über Policies fetzulegen, was bei foo() gemacht werden soll.</p>
<p>Der erste Ansatz dahingehend ist:</p>
<pre><code class="language-cpp">template &lt;typename FooPolicy, typename T, typename U = T&gt;
class Base : public FooPolicy{
public:
    using FooPolicy::doFoo;

    Base (int whatever):
    m_whatever(whatever)
    {}

    ~Base() { /* machs kaputt */ }

    void foo(const T&amp; t) { doFoo(t); }

protected:
    int m_whatever
    // weitere Membervariablen, die von U und T abhängen, weggelassen
};

template &lt;typename U, typename U = T&gt;
class APolicy {
public:
    APolicy(const std::string&amp; bar, Base&lt;U,T&gt;&amp; base):
    m_base(base),
    m_bar(bar)
    {}

    void doFoo(const T&amp; t) { doSomething(t, m_base-&gt;whatever, m_bar); }   

private:
   std::string m_bar;
}

template &lt;typename U, typename U = T&gt;
class BPolicy {
public:
    BPolicy(float baz, Base&lt;U,T&gt;&amp; base):
    m_base(base),
    m_baz(baz)
    {}

    void doFoo(const T&amp; t) { doSomethingElse(t, m_base-&gt;whatever, m_baz); }   

private:
   float m_baz
}

// irgendwo anders
std::vector&lt;Base&lt;A_Policy, int&gt; &gt; vector_of_stuff;

vector_of_stuff[23].foo(42);
</code></pre>
<p>Dabei habe ich im Grunde zwei Probleme: Erstens, der Zugriff auf die in Base gespeicherten Daten. Dazu müsste ich zunächsts einmal die Policies zu &quot;friends&quot; von Base machen, damit sie m_whatever benutzen können. Das ist ja nicht weiter schlimm. Aber auf Ojektebene müssen sie ihr Base-Objekt ja auch kennen, daher der Konstruktor mit Base&amp; base.</p>
<p>Wie aber sieht jetzt der Base-Konstruktor aus?<br />
Angenommen, Base besitzt ein Objekt der Policy, dann müssten die Base-Konstruktoren ja so aussehen:</p>
<pre><code class="language-cpp">Base (const std::string&amp; bar, int whatever):
policy(*this, bar),
m_whatever(whatever)

Base (float baz, int whatever):
policy(*this, baz),
m_whatever(whatever)
</code></pre>
<p>Das ist aber in zweifacher Hinsicht Blödsinn, denn erstens kompiliert es nicht, da es ja immer nur einen Policy-Konstruktor gibt, der ENTWEDER einen String ODER ein float annimmt, jenachdem welche Policy man benutzt,<br />
und zweitens ist mir nicht wohl dabei, in der Initialisierungsliste des Konstruktors den this-Pointer zu dereferenzieren und an jemanden weiterzugeben. Im this-Pointer steht zu dem Zeitpunkt doch wahrscheinlich noch bit-Müll, oder?</p>
<p>Okay, ich hoffe ich habe das Problem verständlich dargestellt.<br />
Die Grundfrage ist also: wie refaktorisiert man abgeleitete Klassen in Policies, wenn sie Daten der Basisklasse benutzen UND subtil unterschiedliche Konstruktoren haben?</p>
<p>Philipp</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1968514</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1968514</guid><dc:creator><![CDATA[PhilippM]]></dc:creator><pubDate>Thu, 21 Oct 2010 13:40:18 GMT</pubDate></item><item><title><![CDATA[Reply to Ableitung durch Policy ersetzen on Thu, 21 Oct 2010 14:11:38 GMT]]></title><description><![CDATA[<p>Suche mal nach dem &quot;Curiously Recurring Template Pattern&quot;...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1968534</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1968534</guid><dc:creator><![CDATA[Tachyon]]></dc:creator><pubDate>Thu, 21 Oct 2010 14:11:38 GMT</pubDate></item><item><title><![CDATA[Reply to Ableitung durch Policy ersetzen on Thu, 21 Oct 2010 14:12:53 GMT]]></title><description><![CDATA[<p>Davon habe ich schonmal was gehört, ja.</p>
<p>Das ist</p>
<pre><code class="language-cpp">class Base: public Derived&lt;Base&gt;
</code></pre>
<p>oder?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1968537</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1968537</guid><dc:creator><![CDATA[PhilippM]]></dc:creator><pubDate>Thu, 21 Oct 2010 14:12:53 GMT</pubDate></item><item><title><![CDATA[Reply to Ableitung durch Policy ersetzen on Thu, 21 Oct 2010 14:13:52 GMT]]></title><description><![CDATA[<p>PhilippM schrieb:</p>
<blockquote>
<p>Davon habe ich schonmal was gehört, ja.</p>
<p>Das ist</p>
<pre><code class="language-cpp">class Base: public Derived&lt;Base&gt;
</code></pre>
<p>oder?</p>
</blockquote>
<p>Jap, und das ermöglicht quasi statische Polymorphie.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1968538</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1968538</guid><dc:creator><![CDATA[Tachyon]]></dc:creator><pubDate>Thu, 21 Oct 2010 14:13:52 GMT</pubDate></item><item><title><![CDATA[Reply to Ableitung durch Policy ersetzen on Thu, 21 Oct 2010 15:00:15 GMT]]></title><description><![CDATA[<p>Habe das mal eingebaut im Beispielcode.</p>
<p>Aber irgendwie macht die Kombination von Policies und CRTP keinen Sinn, da sich dann eine Kreisvererbung ergibt.</p>
<p>Hier der Code:</p>
<pre><code class="language-cpp">#include &lt;string&gt;
#include &lt;vector&gt;

template &lt;typename FooPolicy, typename T, typename U = T&gt;
class Base : public FooPolicy{
public:
    using FooPolicy::doFoo;

    Base (int whatever):
    m_whatever(whatever)
    {}

    ~Base() { /* machs kaputt */ }

    void foo(const T&amp; t) { doFoo(t); }

protected:
    int m_whatever;
    // weitere Membervariablen, die von U und T abhängen, weggelassen
};

template &lt;typename CRTPBase, typename T, typename U = T&gt;
class APolicy : public CRTPBase {
public:
    APolicy(const std::string&amp; bar):
    m_bar(bar)
    {}

    void doFoo(const T&amp; t) { doSomething(t, this-&gt;whatever, m_bar); }

private:
   std::string m_bar;
};

template &lt;typename CRTPBase, typename T, typename U = T&gt;
class BPolicy: public CRTPBase {
public:
    BPolicy(float baz):
    m_baz(baz)
    {}

    void doFoo(const T&amp; t) { doSomethingElse(t, this-&gt;whatever, m_baz); }

private:
   float m_baz;
};

// irgendwo anders
Base&lt;APolicy&lt;typename Base, int&gt;, int&gt; stuff(12);
</code></pre>
<p>gcc 4.4 versteht ihn nicht:</p>
<pre><code>../crtp-test/main.cpp:49:32: error: wrong number of template arguments (1, should be 3)
../crtp-test/main.cpp:23:7: error: provided for ‘template&lt;class CRTPBase, class T, class U&gt; class APolicy’
../crtp-test/main.cpp:49:38: error: template argument 1 is invalid
../crtp-test/main.cpp:49:45: error: invalid type in declaration before ‘(’ token
</code></pre>
<p>und ich ehrlich gesagt gerade auch nicht.<br />
Base&lt;APolicy&lt;Base&gt; &gt; ist doch eigentlich Base&lt;APolicy&lt;Base&lt;APolicy&lt; ....<br />
Da habe ich doch eine seltsame Schleife konstruiert, oder???</p>
<p>Philipp</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1968563</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1968563</guid><dc:creator><![CDATA[PhilippM]]></dc:creator><pubDate>Thu, 21 Oct 2010 15:00:15 GMT</pubDate></item><item><title><![CDATA[Reply to Ableitung durch Policy ersetzen on Thu, 21 Oct 2010 15:14:18 GMT]]></title><description><![CDATA[<p>Du sollst es ja auch nicht mehr über Policies machen, sondern wieder Deinen ersten Ansatz nehmen. Nur eben mit statischer anstatt mit dynamischer Polymorphie. Sonst wird es schwierig, mit den unterschiedlichen Konstruktoren...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1968568</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1968568</guid><dc:creator><![CDATA[Tachyon]]></dc:creator><pubDate>Thu, 21 Oct 2010 15:14:18 GMT</pubDate></item><item><title><![CDATA[Reply to Ableitung durch Policy ersetzen on Thu, 21 Oct 2010 15:56:38 GMT]]></title><description><![CDATA[<p>Achtung:</p>
<pre><code class="language-cpp">class Base: public Derived&lt;Base&gt;
</code></pre>
<p>ist natürlich verkehrtherum.<br />
es muss</p>
<pre><code class="language-cpp">class Derived : public Base&lt;Derived&gt;
</code></pre>
<p>heissen.</p>
<p>Dann hast du statt</p>
<pre><code class="language-cpp">template &lt;typename CRTPBase, typename T, typename U = T&gt;
class APolicy : public CRTPBase {
</code></pre>
<p>einfach ein</p>
<pre><code class="language-cpp">template &lt;typename T, typename U = T&gt;
class APolicy : public Base&lt;APolicy, T, U&gt; {
</code></pre>
<p>APolicy weiss ja wer seine Base ist.<br />
Und Base erbt natürlich nicht von APolicy.<br />
Sondern sieht nur so aus:</p>
<pre><code class="language-cpp">template &lt;typename FooPolicy, typename T, typename U = T&gt;
class Base{
</code></pre>
<p>Base weiss aber dass es in Wirklichkeit ein FooPolicy ist und kann daher folgendes machen:</p>
<pre><code class="language-cpp">void foo() {
  static_cast&lt;FooPolicy*&gt;(this)-&gt;doFoo();
}
</code></pre>
<p>um eine virtuelle doFoo funktion zu simulieren.</p>
<p>PS:<br />
da Base ja über FooPolicy zugriff auf T und U bekommen kann braucht es selber diese garnicht als template parameter...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1968585</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1968585</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Thu, 21 Oct 2010 15:56:38 GMT</pubDate></item><item><title><![CDATA[Reply to Ableitung durch Policy ersetzen on Thu, 21 Oct 2010 15:56:58 GMT]]></title><description><![CDATA[<p>Ha!<br />
So geht's:</p>
<pre><code class="language-cpp">template &lt;typename Policy, typename T, typename U = T&gt;
class Base {
public:

    Base (int whatever):
    m_whatever(whatever)
    {}

    ~Base() { /* machs kaputt */ }

    void foo(const T&amp; t) { static_cast&lt;Policy*&gt;(this)-&gt;doFoo(t); }

protected:
    int m_whatever;
    // weitere Membervariablen, die von U und T abhängen, weggelassen
};

template &lt;typename T, typename U = T&gt;
class APolicy : public Base&lt;APolicy&lt;T,U&gt;, T, U&gt; {
public:
    APolicy(const std::string&amp; bar, int whatever):
    Base&lt;APolicy, T,U&gt;(whatever),
    m_bar(bar)
    {}

    void doFoo(const T&amp; t) { doSomething(t, this-&gt;whatever, m_bar); }

private:
   std::string m_bar;
};

template &lt;typename T, typename U = T&gt;
class BPolicy: public Base&lt;BPolicy&lt;T,U&gt;, T, U&gt; {
public:
    BPolicy(float baz, int whatever):
    Base&lt;BPolicy, T, U&gt;(whatever),
    m_baz(baz)
    {}

    void doFoo(const T&amp; t) { doSomethingElse(t, this-&gt;whatever, m_baz); }

private:
   float m_baz;
};

// irgendwo anders
APolicy&lt;int&gt; stuff(&quot;Hallo&quot;, 42);
</code></pre>
<p>Bleibt die Frage:<br />
Wann setze ich denn dann Policies ein, wenn statische Polymorphie durch CRTP erreicht wird?</p>
<p>Philipp</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1968588</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1968588</guid><dc:creator><![CDATA[PhilippM]]></dc:creator><pubDate>Thu, 21 Oct 2010 15:56:58 GMT</pubDate></item><item><title><![CDATA[Reply to Ableitung durch Policy ersetzen on Thu, 21 Oct 2010 15:57:57 GMT]]></title><description><![CDATA[<p>@ShadeOfMine: GMTA oder FSD ? <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f603.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--grinning_face_with_big_eyes"
      title=":D"
      alt="😃"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/1968591</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1968591</guid><dc:creator><![CDATA[PhilippM]]></dc:creator><pubDate>Thu, 21 Oct 2010 15:57:57 GMT</pubDate></item><item><title><![CDATA[Reply to Ableitung durch Policy ersetzen on Thu, 21 Oct 2010 16:13:46 GMT]]></title><description><![CDATA[<p>PhilippM schrieb:</p>
<blockquote>
<p>Bleibt die Frage:<br />
Wann setze ich denn dann Policies ein, wenn statische Polymorphie durch CRTP erreicht wird?</p>
</blockquote>
<p>Policies haben ja weniger mit der herkömmlichen Polymorphie zu tun, sondern mehr mit dem Strategy Design Pattern. Policies bieten dir die Möglichkeit teile der Klasse unterschiedlich zu konfigurieren.</p>
<p>Ein Beispiel von Policies sind zB die allocatoren in der STL. Wenn diese auch etwas grottig sind. char_traits von Strings sind ein anderes Beispiel.</p>
<p>Du nimmst Policies also zum verändern eines Teils des Verhaltens. Während du Vererbung einsetzt um das Verhalten zu erweitern.</p>
<p>Natürlich können die Anwendungszwecke verschwimmen. zB ist in .NET eine SynchronizedList von List abgeleitet, obwohl man Synchronization auch als Policy einbauen könnte. Wo Ableitung aber Probleme macht ist, wenn man 2 Teile konfigurieren will. zB Synchronization und OwnerShip der Elemente in der Liste (soll die Liste selber das delete machen, wie boost::ptr_list oder sich wie std::list verhalten).</p>
<p>Man müsste für Vererbung nun eine SynchronizedList und eine OwningList und einen OwningSynchronizedList erstellen. Mit Policies macht man einfach: List&lt;Synchronized, Owning&gt;.</p>
<p>Was man durch Policy Based Design aber verliert ist die Polymorphie.</p>
<p>PS:<br />
Wohl eher: ich poste zu langsam oder du denkst zu schnell <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>
]]></description><link>https://www.c-plusplus.net/forum/post/1968597</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1968597</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Thu, 21 Oct 2010 16:13:46 GMT</pubDate></item><item><title><![CDATA[Reply to Ableitung durch Policy ersetzen on Thu, 21 Oct 2010 16:17:03 GMT]]></title><description><![CDATA[<p>Shade Of Mine schrieb:</p>
<blockquote>
<p>Policies haben ja weniger mit der herkömmlichen Polymorphie zu tun, sondern mehr mit dem Strategy Design Pattern. Policies bieten dir die Möglichkeit teile der Klasse unterschiedlich zu konfigurieren.<br />
Was man durch Policy Based Design aber verliert ist die Polymorphie.</p>
</blockquote>
<p>Danke! Das ist der Denkansatz, der mir gefehlt hat.</p>
<p>Jetzt hab ich aber noch eine low-level Frage: Was bringt mir das fürn Vorteil gegenüber den virtuellen Funktionen?</p>
<p>Bei virtellen Funktionen muss ich den Funktionspointer dereferenzieren, hier muss ich</p>
<pre><code class="language-cpp">static_cast&lt;Policy*&gt;(this)-&gt;doFoo(t);
</code></pre>
<p>ebenfalls dem Pointer folgen, um an die Funktion zu kommen.</p>
<p>Wo ist da jetzt der Laufzeitvorteil der &quot;Compilezeitpolymorphie&quot;?</p>
<p>Philipp</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1968603</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1968603</guid><dc:creator><![CDATA[PhilippM]]></dc:creator><pubDate>Thu, 21 Oct 2010 16:17:03 GMT</pubDate></item><item><title><![CDATA[Reply to Ableitung durch Policy ersetzen on Thu, 21 Oct 2010 16:36:03 GMT]]></title><description><![CDATA[<p>PhilippM schrieb:</p>
<blockquote>
<p>Jetzt hab ich aber noch eine low-level Frage: Was bringt mir das fürn Vorteil gegenüber den virtuellen Funktionen?</p>
<p>Bei virtellen Funktionen muss ich den Funktionspointer dereferenzieren, hier muss ich</p>
<pre><code class="language-cpp">static_cast&lt;Policy*&gt;(this)-&gt;doFoo(t);
</code></pre>
<p>ebenfalls dem Pointer folgen, um an die Funktion zu kommen.</p>
<p>Wo ist da jetzt der Laufzeitvorteil der &quot;Compilezeitpolymorphie&quot;?</p>
</blockquote>
<p>Virtuelle funktionen kosten mehr als nur eine zeiger dereferenzierung.<br />
Der cast hier beim crtp ist aber gratis, static_cast ist das in der regel. Es wird ja nur gesagt: das ist ein foo.</p>
<p>Bei virtuellen funktionen hast du ein dynamisches dispatching da this ja auf alles zeigen kann. Und sobald du eine virtuelle funktion hast brauchst einen rattenschwanz an runtime type identification (um imer wissen zu koennen was this ist). Weitesr kann man virtuelle funktionen nicht gut inlinen.</p>
<p>Klingt jetzt als waeren virtuelle funktionen sehr teuer, sind sie aber nicht. In java ist zb jede funktion virtuell und es ist kein problem. Es ist also eine minimale optimierung, mehr nicht.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1968614</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1968614</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Thu, 21 Oct 2010 16:36:03 GMT</pubDate></item><item><title><![CDATA[Reply to Ableitung durch Policy ersetzen on Thu, 21 Oct 2010 16:49:10 GMT]]></title><description><![CDATA[<p>Super, danke für die Erklärung.<br />
Na, dann bin ich ja mal auf den nächsten Profile-Lauf gespannt. Die &quot;foo&quot; funktion wird nämlich auf ~500 Objekten 50 mal pro Sekunde aufgerufen. Ob sich da was bemerkbar macht?</p>
<p>Philipp</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1968625</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1968625</guid><dc:creator><![CDATA[PhilippM]]></dc:creator><pubDate>Thu, 21 Oct 2010 16:49:10 GMT</pubDate></item><item><title><![CDATA[Reply to Ableitung durch Policy ersetzen on Thu, 21 Oct 2010 17:00:07 GMT]]></title><description><![CDATA[<p>PhilippM schrieb:</p>
<blockquote>
<p>Ob sich da was bemerkbar macht?</p>
</blockquote>
<p>Poste dann bitte die Ergebnisse.<br />
Performance haengt an vielen Faktoren. Schneller wird es sicher sein, aber ob es merkbar schneller ist - das wird spannend.</p>
<p>PS:<br />
mein letzter Post war in der UBahn geschrieben, nicht dass ich sonst so eine tolle Rechtschreibung haette, aber *brr* sieht der grottig aus.<br />
*Note to self* In der UBahn nur lesen, nicht schreiben.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1968635</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1968635</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Thu, 21 Oct 2010 17:00:07 GMT</pubDate></item><item><title><![CDATA[Reply to Ableitung durch Policy ersetzen on Thu, 21 Oct 2010 17:27:20 GMT]]></title><description><![CDATA[<p>Jetzt habe ich aber wieder ein Problem:</p>
<p>Vorher:</p>
<pre><code class="language-cpp">class FooInt {
public:
    FooInt(Base&lt;int&gt;* base_pointer):
    m_base_pointer(base_pointer);
private:
    Base&lt;int&gt;* m_base_pointer;
};
</code></pre>
<p>hängt ja jetzt vom konkreten Typ ab.</p>
<p>Daher jetzt:</p>
<pre><code class="language-cpp">template &lt;template &lt;typename T&gt; class Concrete&gt;
class FooInt {
public:
    FooInt(Concrete&lt;int&gt;* data);
private:
    Concrete&lt;int&gt;* m_concrete_pointer;
};
</code></pre>
<p>Wenn ich den Konstruktor für int implementieren will:</p>
<pre><code class="language-cpp">template &lt;template &lt;&gt; class Concrete&lt;int&gt; &gt;
    FooInt&lt;Concrete&lt;int&gt; &gt;::FooInt(Concrete&lt;int&gt;* data):
            m_concrete_pointer(data)
    {
    }
</code></pre>
<p>Fliegt mir alles um die Ohren:</p>
<pre><code>error: expected identifier before ‘&gt;’ token
error: expected ‘&gt;’ before ‘&lt;’ token
error: type/value mismatch at argument 1 in template parameter list for ‘template&lt;int &lt;anonymous&gt; &gt; class Concrete’
expected a constant of type ‘int’, got ‘int’
error: template argument 1 is invalid
type/value mismatch at argument 1 in template parameter list for ‘template&lt;int &lt;anonymous&gt; &gt; class Concrete’
expected a constant of type ‘int’, got ‘int’
error: declaration of template ‘template&lt;template&lt;int &lt;anonymous&gt; &gt; class Concrete&gt; int FooInt(int*)’
</code></pre>
<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /></p>
<p>Hilfe!<br />
Muss ich den Base&lt;int&gt;* pointer jetzt durch einen Concrete&lt;int&gt;* pointer ersetzen oder durch einen Base&lt;Concrete&lt;int&gt;, int&gt;* Pointer?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1968652</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1968652</guid><dc:creator><![CDATA[PhilippM]]></dc:creator><pubDate>Thu, 21 Oct 2010 17:27:20 GMT</pubDate></item><item><title><![CDATA[Reply to Ableitung durch Policy ersetzen on Thu, 21 Oct 2010 18:22:09 GMT]]></title><description><![CDATA[<p>Disregard.</p>
<p>So, das Refaktoring ist durch. Meine Fresse, hab ich da wieder write-only Code produziert.</p>
<p>Ich zitiere mal zusammenhanglos einen Konstruktor, der heute entstanden ist:</p>
<pre><code class="language-cpp">template &lt;template &lt;typename T, typename U=T&gt; class SimAccess, typename Packet, typename Metadata, typename SimType, typename CalcType = SimType, typename BusType = CalcType&gt;
    class SendableData : public TypelessSendableData&lt;Packet, Metadata&gt; {
    public:
        SendableData(SimAccess&lt;SimType, CalcType&gt;* sim_data,
                     PrioType priority = Constant,
                     SimAccess&lt;int&gt;* suspend_ref = 0,
                     SimAccess&lt;int&gt;* dyn_length_ref = 0):
        m_sim_data(sim_data),
        m_priority(priority),
        m_force_outdated(false),
     ....
</code></pre>
<p>Man gebe sich mal die länge der Template-Argumente.<br />
Aber erster positiver Effekt: Das Binary ist etwa 5% kleiner geworden!</p>
<p>Bin mal gespannt aufs Laufzeitverhalten.</p>
<p>Philipp</p>
]]></description><link>https://www.c-plusplus.net/forum/post/1968680</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/1968680</guid><dc:creator><![CDATA[PhilippM]]></dc:creator><pubDate>Thu, 21 Oct 2010 18:22:09 GMT</pubDate></item></channel></rss>