<?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[Allocator-agnostisches Clone, resp. virtuelle Template-Methoden]]></title><description><![CDATA[<p>Hiho,</p>
<p>ich habe in meinem Programm eine polymorphe Hierarchie, wobei ich meist nur Basisklassenzeiger speichere. Was ich nun haben möchte, ist, dass ich <em>deep Copies</em> von beliebigen Instanzen machen kann, nur anhand ihres Basisklassenzeigers. Die kanonische Lösung, einfach einen <em>smart Pointer</em> zurückzugeben, ist nicht zufriedenstellend, weil ich unterschiedliche Allokatoren verwenden möchte. Die kommenden, polymorphen Allokatoren entschärfen dieses Problem weitgehend, aber auf Kosten von zusätzlicher Komplexität.<br />
Da wir C++-Leute künstliche Einschränkungen (Java) ablehnen, verstehe ich nicht, wieso virtuelle Template-Methoden, die dieses und alle anderen Probleme dieser Gattung elegant lösten, nicht bereits Teil des Standards sind. Eine Lösung die mir vorschwebt, sähe in Etwa so aus:</p>
<pre><code>struct foo
{
	template&lt; typename allocator_t &gt;
	virtual std::unique_ptr&lt; foo, wrapper&lt; allocator_t &gt; &gt; clone( allocator_t&amp;&amp; allocator ) const
	{
		// alloziert Speicher für foo
	}	
	template&lt; typename allocator_t &gt;
	std::unique_ptr&lt; foo, allocator_t &gt; clone() const
	{
		return clone&lt; allocator_t &gt;( {} );
	}
};
struct bar : foo
{
	template&lt; typename allocator_t &gt;
	virtual std::unique_ptr&lt; foo, wrapper&lt; allocator_t &gt; &gt; clone( allocator_t&amp;&amp; allocator ) const override
	{
		// alloziert Speicher für bar
	}
};
</code></pre>
<p>Und wenn ich nun <code>foo{}-&gt;clone&lt; logging_alloc_t &gt;();</code> und <code>bar{}-&gt;clone&lt; pool_alloc_t &gt;();</code> aufrufe, dann würde der Compiler zwei virtuelle Funktionen / Funktionszeiger in der Basisklasse generieren, eine mit der Signatur <code>( foo::* )( logging_alloc_t&amp;&amp; ) const</code> und die andere <code>( foo::* )( pool_alloc_t&amp;&amp; ) const</code> . Das Template wäre dann nur dazu da, virtuelle Funktionen automatisch zu definieren.</p>
<p>Genereller betrachtet beläuft sich das Problem darauf, dass man im Moment gezwungen ist, <em>Interfaces</em> zu schreiben, wenn man Laufzeitpolymorphie und Template-Code mischt. Ein weiteres Beispiel:</p>
<pre><code>struct foo
{
	template&lt; typename char_t, typename traits_t &gt;
	virtual std::basic_ostream&lt; char_t, traits_t &gt;&amp; print( std::basic_ostream&lt; char_t, traits_t &gt;&amp; destination ) const
	{
		// ...
	}
};
struct bar : foo
{
	template&lt; typename char_t, typename traits_t &gt;
	virtual std::basic_ostream&lt; char_t, traits_t &gt;&amp; print( std::basic_ostream&lt; char_t, traits_t &gt;&amp; destination ) const override
	{
		// ...
	}
};
</code></pre>
<p>Statt für jedes unterstütztes <em>Encoding</em> manuell eine weitere virtuelle Methode zu schreiben, würde diese Variante zur Compilezeit die passenden virtuellen Methoden generieren, abhängig davon, wie <code>print</code> im Code tatsächlich instantiiert wird. Die Alternative hierzu ist ein weiteres <em>Interface</em> zu schreiben, das vom statischen Typensystem unabhängig ist. Für dieses Problem insbesondere existiert glücklicherweise bereits eine Lösung: <code>std::u32string</code> , der dann von der Funktion zurückgegeben würde. Der zusätzliche Adapter, dieses Typensystem-unabhängige <em>Interface</em>, den <code>std::u32string</code> , dann letztendlich in die Zielcodierung zu konvertieren, ist minimal. Aber auch diese Lösung birgt Probleme: die gesamte Ausgabe in einem zusammenhängenden (<em>contiguous</em>) Speichersegment zwischenzuspeichern, und dann noch in UTF-32, ist, insbesondere bei größeren Ausgaben, inakzeptabel.</p>
<p>Das ist dann erst die Spitze des Eisbergs, denn für viele andere Probleme existiert kein so komfortables, vorgefertigtes <em>Interface</em>, wie im folgendem Falle:<br />
Es existiert ein Vektor von <code>std::unique_ptr&lt; filter_base &gt;</code> . Es gibt verschiedene Klassen, die von <code>filter_base</code> abgeleitet sind, aber sie haben alle gemeinsam, dass sie auf Matrizen (hier: 2D-Pixelmatrizen, resp. Bilder) anwendbar sind. Nun möchte ich während der Laufzeit meine Bildmatrix von 24-bit RGB zu <code>floating point</code> RGB ändern. Wie ist es nun möglich, dass der Vektor an Filtern ungeändert bleibt, die einzelnen Filter aber dennoch auf die neue Bildmatrix mit einem anderen statischen Dateityp angewandt werden können? Dazu müsste ich also manuell eine neue virtuelle Methode in <code>filter_base</code> einführen:</p>
<pre><code>struct filter_base
{
	virtual ~filter_base() = default;

	virtual void apply( matrix_24bit_rgb&amp; ) const = 0;
	virtual void apply( matrix_flt_rgb&amp; ) const = 0;
};
struct darken : filter_base
{
	virtual void apply( matrix_24bit_rgb&amp; mat ) const
	{
		for( auto&amp; i : mat )
			i /= 2;
	}
	virtual void apply( matrix_flt_rgb&amp; mat ) const
	{
		for( auto&amp; i : mat )
			i /= 2;
	}
};
</code></pre>
<p>Für jeden weiteren Matrizentyp, den ich mit den Filtern unterstützen will, muss ich sowohl in der Basisklasse, als auch in jeder einzelnen abgeleiteten Klasse manuell eine weitere Überladung einfügen, auch wenn die Implementierungen identisch sind. Diese Variante hat den weiteren Nachteil, dass in jedem Fall ein <em>vtable</em>-Eintrag erstellt wird, unabhängig davon, ob eine bestimmte Überladung dann im finalen Programm tatsächlich verwendet wird. Dies wäre nicht der Fall mit Templates, die wirklich nur dann instantiiert werden, wenn sie gebraucht werden.</p>
<p>Mir ist bewusst, das dieses Sprachwerkzeug unweigerlich auch Risiken mit sich bringt. Beispielsweise würden die Leute früher oder später definitiv dazu verleitet, Iteratoren oder <em>Ranges</em> mittels dieses Mechanismus zu übergeben, was dazu führt, dass die <em>vtable</em> komplett zugemüllt wird. Meine Vorstellung beläuft sich darauf, dieses Sprachmittel nur einzusetzen, wenn weniger als ca. ein Dutzend Instantiierungen zu erwarten sind: 1 von ~5 <em>Encodings</em>, 1 von ~10 arithmetischen Typen, 1 von ~10 Containern, 1 von ~5 Layouts etc.</p>
<p>Zur Implementierung: Ich bin mir auch über die Implikation im Klaren, dass die Größe einer Klasse davon abhängt, wie ihre Methoden (und die, der abgeleiteten Klassen) instantiiert werden, wobei ich auf die Schnelle kein Problem damit sehe.</p>
<p>Wieso gibt es das nicht bereits? Und wie soll man das Problem mit <code>filter_base</code> zufriedenstellend lösen, ohne dass besagtes Sprachmittel zur Verfügung steht?</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/340340/allocator-agnostisches-clone-resp-virtuelle-template-methoden</link><generator>RSS for Node</generator><lastBuildDate>Sat, 11 Apr 2026 05:38:26 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/340340.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 01 Nov 2016 14:47:14 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Allocator-agnostisches Clone, resp. virtuelle Template-Methoden on Tue, 01 Nov 2016 14:47:14 GMT]]></title><description><![CDATA[<p>Hiho,</p>
<p>ich habe in meinem Programm eine polymorphe Hierarchie, wobei ich meist nur Basisklassenzeiger speichere. Was ich nun haben möchte, ist, dass ich <em>deep Copies</em> von beliebigen Instanzen machen kann, nur anhand ihres Basisklassenzeigers. Die kanonische Lösung, einfach einen <em>smart Pointer</em> zurückzugeben, ist nicht zufriedenstellend, weil ich unterschiedliche Allokatoren verwenden möchte. Die kommenden, polymorphen Allokatoren entschärfen dieses Problem weitgehend, aber auf Kosten von zusätzlicher Komplexität.<br />
Da wir C++-Leute künstliche Einschränkungen (Java) ablehnen, verstehe ich nicht, wieso virtuelle Template-Methoden, die dieses und alle anderen Probleme dieser Gattung elegant lösten, nicht bereits Teil des Standards sind. Eine Lösung die mir vorschwebt, sähe in Etwa so aus:</p>
<pre><code>struct foo
{
	template&lt; typename allocator_t &gt;
	virtual std::unique_ptr&lt; foo, wrapper&lt; allocator_t &gt; &gt; clone( allocator_t&amp;&amp; allocator ) const
	{
		// alloziert Speicher für foo
	}	
	template&lt; typename allocator_t &gt;
	std::unique_ptr&lt; foo, allocator_t &gt; clone() const
	{
		return clone&lt; allocator_t &gt;( {} );
	}
};
struct bar : foo
{
	template&lt; typename allocator_t &gt;
	virtual std::unique_ptr&lt; foo, wrapper&lt; allocator_t &gt; &gt; clone( allocator_t&amp;&amp; allocator ) const override
	{
		// alloziert Speicher für bar
	}
};
</code></pre>
<p>Und wenn ich nun <code>foo{}-&gt;clone&lt; logging_alloc_t &gt;();</code> und <code>bar{}-&gt;clone&lt; pool_alloc_t &gt;();</code> aufrufe, dann würde der Compiler zwei virtuelle Funktionen / Funktionszeiger in der Basisklasse generieren, eine mit der Signatur <code>( foo::* )( logging_alloc_t&amp;&amp; ) const</code> und die andere <code>( foo::* )( pool_alloc_t&amp;&amp; ) const</code> . Das Template wäre dann nur dazu da, virtuelle Funktionen automatisch zu definieren.</p>
<p>Genereller betrachtet beläuft sich das Problem darauf, dass man im Moment gezwungen ist, <em>Interfaces</em> zu schreiben, wenn man Laufzeitpolymorphie und Template-Code mischt. Ein weiteres Beispiel:</p>
<pre><code>struct foo
{
	template&lt; typename char_t, typename traits_t &gt;
	virtual std::basic_ostream&lt; char_t, traits_t &gt;&amp; print( std::basic_ostream&lt; char_t, traits_t &gt;&amp; destination ) const
	{
		// ...
	}
};
struct bar : foo
{
	template&lt; typename char_t, typename traits_t &gt;
	virtual std::basic_ostream&lt; char_t, traits_t &gt;&amp; print( std::basic_ostream&lt; char_t, traits_t &gt;&amp; destination ) const override
	{
		// ...
	}
};
</code></pre>
<p>Statt für jedes unterstütztes <em>Encoding</em> manuell eine weitere virtuelle Methode zu schreiben, würde diese Variante zur Compilezeit die passenden virtuellen Methoden generieren, abhängig davon, wie <code>print</code> im Code tatsächlich instantiiert wird. Die Alternative hierzu ist ein weiteres <em>Interface</em> zu schreiben, das vom statischen Typensystem unabhängig ist. Für dieses Problem insbesondere existiert glücklicherweise bereits eine Lösung: <code>std::u32string</code> , der dann von der Funktion zurückgegeben würde. Der zusätzliche Adapter, dieses Typensystem-unabhängige <em>Interface</em>, den <code>std::u32string</code> , dann letztendlich in die Zielcodierung zu konvertieren, ist minimal. Aber auch diese Lösung birgt Probleme: die gesamte Ausgabe in einem zusammenhängenden (<em>contiguous</em>) Speichersegment zwischenzuspeichern, und dann noch in UTF-32, ist, insbesondere bei größeren Ausgaben, inakzeptabel.</p>
<p>Das ist dann erst die Spitze des Eisbergs, denn für viele andere Probleme existiert kein so komfortables, vorgefertigtes <em>Interface</em>, wie im folgendem Falle:<br />
Es existiert ein Vektor von <code>std::unique_ptr&lt; filter_base &gt;</code> . Es gibt verschiedene Klassen, die von <code>filter_base</code> abgeleitet sind, aber sie haben alle gemeinsam, dass sie auf Matrizen (hier: 2D-Pixelmatrizen, resp. Bilder) anwendbar sind. Nun möchte ich während der Laufzeit meine Bildmatrix von 24-bit RGB zu <code>floating point</code> RGB ändern. Wie ist es nun möglich, dass der Vektor an Filtern ungeändert bleibt, die einzelnen Filter aber dennoch auf die neue Bildmatrix mit einem anderen statischen Dateityp angewandt werden können? Dazu müsste ich also manuell eine neue virtuelle Methode in <code>filter_base</code> einführen:</p>
<pre><code>struct filter_base
{
	virtual ~filter_base() = default;

	virtual void apply( matrix_24bit_rgb&amp; ) const = 0;
	virtual void apply( matrix_flt_rgb&amp; ) const = 0;
};
struct darken : filter_base
{
	virtual void apply( matrix_24bit_rgb&amp; mat ) const
	{
		for( auto&amp; i : mat )
			i /= 2;
	}
	virtual void apply( matrix_flt_rgb&amp; mat ) const
	{
		for( auto&amp; i : mat )
			i /= 2;
	}
};
</code></pre>
<p>Für jeden weiteren Matrizentyp, den ich mit den Filtern unterstützen will, muss ich sowohl in der Basisklasse, als auch in jeder einzelnen abgeleiteten Klasse manuell eine weitere Überladung einfügen, auch wenn die Implementierungen identisch sind. Diese Variante hat den weiteren Nachteil, dass in jedem Fall ein <em>vtable</em>-Eintrag erstellt wird, unabhängig davon, ob eine bestimmte Überladung dann im finalen Programm tatsächlich verwendet wird. Dies wäre nicht der Fall mit Templates, die wirklich nur dann instantiiert werden, wenn sie gebraucht werden.</p>
<p>Mir ist bewusst, das dieses Sprachwerkzeug unweigerlich auch Risiken mit sich bringt. Beispielsweise würden die Leute früher oder später definitiv dazu verleitet, Iteratoren oder <em>Ranges</em> mittels dieses Mechanismus zu übergeben, was dazu führt, dass die <em>vtable</em> komplett zugemüllt wird. Meine Vorstellung beläuft sich darauf, dieses Sprachmittel nur einzusetzen, wenn weniger als ca. ein Dutzend Instantiierungen zu erwarten sind: 1 von ~5 <em>Encodings</em>, 1 von ~10 arithmetischen Typen, 1 von ~10 Containern, 1 von ~5 Layouts etc.</p>
<p>Zur Implementierung: Ich bin mir auch über die Implikation im Klaren, dass die Größe einer Klasse davon abhängt, wie ihre Methoden (und die, der abgeleiteten Klassen) instantiiert werden, wobei ich auf die Schnelle kein Problem damit sehe.</p>
<p>Wieso gibt es das nicht bereits? Und wie soll man das Problem mit <code>filter_base</code> zufriedenstellend lösen, ohne dass besagtes Sprachmittel zur Verfügung steht?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2513759</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2513759</guid><dc:creator><![CDATA[autismo]]></dc:creator><pubDate>Tue, 01 Nov 2016 14:47:14 GMT</pubDate></item><item><title><![CDATA[Reply to Allocator-agnostisches Clone, resp. virtuelle Template-Methoden on Sat, 05 Nov 2016 16:22:30 GMT]]></title><description><![CDATA[<p>Weiß niemand eine Lösung für mein Problem mit den polymorphen Filtern, die auf Matrizen unterschiedlichen Typs angewandt werden können sollen?<br />
Ist der Post zu lange oder zu unverständlich?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2514179</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2514179</guid><dc:creator><![CDATA[autismo]]></dc:creator><pubDate>Sat, 05 Nov 2016 16:22:30 GMT</pubDate></item><item><title><![CDATA[Reply to Allocator-agnostisches Clone, resp. virtuelle Template-Methoden on Sat, 05 Nov 2016 17:38:13 GMT]]></title><description><![CDATA[<blockquote>
<p>Da wir C++-Leute künstliche Einschränkungen (Java) ablehnen, verstehe ich nicht, wieso virtuelle Template-Methoden, die dieses und alle anderen Probleme dieser Gattung elegant lösten, nicht bereits Teil des Standards sind.</p>
</blockquote>
<p>Die vtable der Klasse, die das Template enthält, muss sich je nach den Instantiierungen des Membertemplates anpassen: In zwei Übersetzungseinheiten kann eine übereinstimmend definierte Klasse unterschiedliche vtables haben. Das ist einfach <em>total</em> inkompatibel mit der ODR.</p>
<p>Ich habe das vage Gefühl, dass du die Idee von &quot;Klassentemplates mit virtuellen Funktionen&quot; mit &quot;Klassen mit virtuellen Funktionstemplates&quot; vermischst; ersteres macht Sinn und ist auch wohlgeformt.</p>
<blockquote>
<p>Für jeden weiteren Matrizentyp, den ich mit den Filtern unterstützen will, muss ich sowohl in der Basisklasse, als auch in jeder einzelnen abgeleiteten Klasse manuell eine weitere Überladung einfügen, auch wenn die Implementierungen identisch sind.</p>
</blockquote>
<p>Na hier liegt doch dein Problem: Du hättest die Matrizentypen polymorph machen müssen, sodass virtuelle Funktionen in einer abstrakten Basisklasse <code>Matrix</code> die implementierungs-unabhängige Funktionalität bereitstellen.</p>
<p>Edit:</p>
<blockquote>
<p>Ist der Post zu lange oder zu unverständlich?</p>
</blockquote>
<p>Ja, er ist recht lang. Du hättest dein Problem vielleicht etwas prägnanter formulieren können. Ausschweifende Darstellungen sind für Antworten klasse, und für Fragen IMO ein no-go, wenn nicht nötig.</p>
<p>Edit²: Nur ein Satzzeichen ergänzt. Ist das übertrieben? Oder ist meine Rechtfertigung dieses Edits übertrieben? Wer weiß. Wahrscheinlich beides.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2514182</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2514182</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Sat, 05 Nov 2016 17:38:13 GMT</pubDate></item><item><title><![CDATA[Reply to Allocator-agnostisches Clone, resp. virtuelle Template-Methoden on Sat, 05 Nov 2016 18:12:29 GMT]]></title><description><![CDATA[<p>Arcoth schrieb:</p>
<blockquote>
<p>Na hier liegt doch dein Problem: Du hättest die Matrizentypen polymorph machen müssen, sodass virtuelle Funktionen in einer abstrakten Basisklasse <code>Matrix</code> die implementierungs-unabhängige Funktionalität bereitstellen.</p>
</blockquote>
<p>Daran hatte ich natürlich auch gedacht, aber um z.B. darken wie im OP zu implementieren, müsste ich dann auch einen polymorphen Wrapper um die Skalare basteln. Und das schlüge dann erst richtig auf die Laufzeit.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2514183</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2514183</guid><dc:creator><![CDATA[autismo]]></dc:creator><pubDate>Sat, 05 Nov 2016 18:12:29 GMT</pubDate></item><item><title><![CDATA[Reply to Allocator-agnostisches Clone, resp. virtuelle Template-Methoden on Sat, 05 Nov 2016 18:40:51 GMT]]></title><description><![CDATA[<p>autismo schrieb:</p>
<blockquote>
<p>um z.B. darken wie im OP zu implementieren, müsste ich dann auch einen polymorphen Wrapper um die Skalare basteln.</p>
</blockquote>
<p>Warum das?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2514185</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2514185</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Sat, 05 Nov 2016 18:40:51 GMT</pubDate></item><item><title><![CDATA[Reply to Allocator-agnostisches Clone, resp. virtuelle Template-Methoden on Mon, 07 Nov 2016 14:40:57 GMT]]></title><description><![CDATA[<p>Arcoth schrieb:</p>
<blockquote>
<p>Warum das?</p>
</blockquote>
<p>Ups, hab' dich falsch verstanden.<br />
Aber dann muss ich noch immer die Base-Klasse von Matrix mit CRPT implementeren, sonst muss ich den Filter doch wieder in jeder abgeleiteten Klasse einzeln implementieren. Und wenn ich das mache, dann kann ich wieder keine Methodenzeiger auf die Basisklasse in einem homogenen Vektor speichern.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2514384</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2514384</guid><dc:creator><![CDATA[autismo]]></dc:creator><pubDate>Mon, 07 Nov 2016 14:40:57 GMT</pubDate></item><item><title><![CDATA[Reply to Allocator-agnostisches Clone, resp. virtuelle Template-Methoden on Mon, 07 Nov 2016 21:07:35 GMT]]></title><description><![CDATA[<p>autismo schrieb:</p>
<blockquote>
<p>Zur Implementierung: Ich bin mir auch über die Implikation im Klaren, dass die Größe einer Klasse davon abhängt, wie ihre Methoden (und die, der abgeleiteten Klassen) instantiiert werden, wobei ich auf die Schnelle kein Problem damit sehe.</p>
</blockquote>
<p>Weiss nicht was du mit &quot;Grösse einer Klasse&quot; meinst. Die grösse der Objekte der Klasse hängt auf jeden Fall nicht davon ab, sondern nur davon ob es überhaupt virtuelle Funktionen gibt oder eben gar keine.</p>
<p>autismo schrieb:</p>
<blockquote>
<p>Wieso gibt es das nicht bereits?</p>
</blockquote>
<p>Also erstmal wäre es denke ich relativ kompliziert und aufwendig zu implementieren.</p>
<p>Dabei müsste erstmal das ganze Programm (d.h. sämtliche Translation Units!) &quot;compiliert&quot; werden (evtl. ohne Code-Generierung), um festzustellen welche Instanzierungen von virtuellen Funktionstemplates benötigt werden. Dann müssten diese instanziert werden. Dabei können weitere Instanzierungen von virtuellen Funktionstemplates dazukommen, d.h. man müsste so lange loopen bis die &quot;Queue&quot; der benötigten Instanzierungen leer ist.<br />
Erst danach weiss man welche VTable-Slots überhaupt benötigt werden und kann dann mit der Code-Generierung anfangen, bzw. damit die ganzen Vtable-Indexe in den generierten Code &quot;hineinzupatchen&quot;.</p>
<p>Nebenbei erfordert das auch ein Feature das in C++98 vorhanden war, und dann, weil es bis auf einen Compiler (Comeau C++) keiner implementiert hatte, im 2011er Standard wieder entfernt wurde. Nämlich &quot;<a href="http://www.comeaucomputing.com/4.0/docs/userman/export.html" rel="nofollow">Exported Templates</a>&quot;.</p>
<p>autismo schrieb:</p>
<blockquote>
<p>Und wie soll man das Problem mit <code>filter_base</code> zufriedenstellend lösen, ohne dass besagtes Sprachmittel zur Verfügung steht?</p>
</blockquote>
<p>Indem man das, was du vollautomatisch haben willst, halbautomatisch macht:</p>
<pre><code class="language-cpp">struct filter_base
{
    virtual ~filter_base() = default;

    virtual void apply( matrix_24bit_rgb&amp; ) const = 0;
    virtual void apply( matrix_flt_rgb&amp; ) const = 0;
};

template &lt;class T&gt;
struct template_filter_impl : public T
{
    virtual void apply( matrix_24bit_rgb&amp; mat ) const
    {
        T::apply_impl(mat);
    }

    virtual void apply( matrix_flt_rgb&amp; mat ) const
    {
        T::apply_impl(mat);
    }
};

struct darken_impl : public filter_base
{
    template &lt;class MAT&gt;
    void apply_impl( MAT&amp; mat ) const
    {
        for( auto&amp; i : mat )
            i /= 2;
    }
};

struct darken : public template_filter_impl&lt;darken_impl&gt;
{
};
</code></pre>
<p>Theoretisch kannst du hier auch das CRTP verwenden, dann könntest du dir die &quot;Zwischenklassen&quot; ( <code>darken_impl</code> &amp; Co) sparen:</p>
<pre><code class="language-cpp">struct filter_base
{
    virtual ~filter_base() = default;

    virtual void apply( matrix_24bit_rgb&amp; ) const = 0;
    virtual void apply( matrix_flt_rgb&amp; ) const = 0;
};

template &lt;class T&gt;
struct template_filter_base : public filter_base
{
    virtual void apply( matrix_24bit_rgb&amp; mat ) const
    {
        static_cast&lt;T const*&gt;(this)-&gt;apply_impl(mat);
    }

    virtual void apply( matrix_flt_rgb&amp; mat ) const
    {
        static_cast&lt;T const*&gt;(this)-&gt;apply_impl(mat);
    }
};

struct darken : template_filter_base&lt;darken&gt;
{
    template &lt;class MAT&gt;
    void apply_impl( MAT&amp; mat ) const
    {
        for( auto&amp; i : mat )
            i /= 2;
    }
};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2514471</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2514471</guid><dc:creator><![CDATA[hustbaer]]></dc:creator><pubDate>Mon, 07 Nov 2016 21:07:35 GMT</pubDate></item></channel></rss>