<?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[TMP: Permutationen von Template-Parametern generieren]]></title><description><![CDATA[<p>Hallo zusammen,</p>
<p>ich überlege gerade, ob man meine Factory-Funktion <code>MakeBar</code> mittels TMP oder sonstwie eleganter hinbekommen könnte, habe aber noch überhaupt keinen Ansatz. Etwas mit Andreischen typelists vielleicht?</p>
<pre><code class="language-cpp">#include &lt;memory&gt;

struct Foo1 {};
struct Foo2 {};
struct Foo3 {};

struct BarBase {};

template&lt;typename T1, typename T2&gt;
struct Bar : public BarBase {};

typedef std::unique_ptr&lt;BarBase&gt; BarPtr;

BarPtr MakeBar( int id1, int id2 ) {
	if ( id1 == 1 &amp;&amp; id2 == 1 )
		return BarPtr( new( Bar&lt;Foo1, Foo1&gt; ) );
	else if ( id1 == 1 &amp;&amp; id2 == 2 )
		return BarPtr( new( Bar&lt;Foo1, Foo2&gt; ) );
	else if ( id1 == 1 &amp;&amp; id2 == 3 )
		return BarPtr( new( Bar&lt;Foo1, Foo3&gt; ) );
	else if ( id1 == 2 &amp;&amp; id2 == 1 )
		return BarPtr( new( Bar&lt;Foo2, Foo1&gt; ) );
	else if ( id1 == 2 &amp;&amp; id2 == 2 )
		return BarPtr( new( Bar&lt;Foo2, Foo2&gt; ) );
	else if ( id1 == 2 &amp;&amp; id2 == 3 )
		return BarPtr( new( Bar&lt;Foo2, Foo3&gt; ) );
	else if ( id1 == 3 &amp;&amp; id2 == 1 )
		return BarPtr( new( Bar&lt;Foo3, Foo1&gt; ) );
	else if ( id1 == 3 &amp;&amp; id2 == 2 )
		return BarPtr( new( Bar&lt;Foo3, Foo2&gt; ) );
	else if ( id1 == 3 &amp;&amp; id2 == 3 )
		return BarPtr( new( Bar&lt;Foo3, Foo3&gt; ) );
	return BarPtr();
}

int main() {
	int userInput1( 2 );
	int userInput2( 3 );
	BarPtr ptr( MakeBar( userInput1, userInput2 ) );
}
</code></pre>
<p>Irgendwelche Ideen, wie man das viele Instanziieren des Klassentemplates nicht mehr manuell machen muss?</p>
<p>Gruß<br />
Dobi</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/303928/tmp-permutationen-von-template-parametern-generieren</link><generator>RSS for Node</generator><lastBuildDate>Mon, 10 Aug 2026 03:54:05 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/303928.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 25 May 2012 11:30:51 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to TMP: Permutationen von Template-Parametern generieren on Fri, 25 May 2012 11:30:51 GMT]]></title><description><![CDATA[<p>Hallo zusammen,</p>
<p>ich überlege gerade, ob man meine Factory-Funktion <code>MakeBar</code> mittels TMP oder sonstwie eleganter hinbekommen könnte, habe aber noch überhaupt keinen Ansatz. Etwas mit Andreischen typelists vielleicht?</p>
<pre><code class="language-cpp">#include &lt;memory&gt;

struct Foo1 {};
struct Foo2 {};
struct Foo3 {};

struct BarBase {};

template&lt;typename T1, typename T2&gt;
struct Bar : public BarBase {};

typedef std::unique_ptr&lt;BarBase&gt; BarPtr;

BarPtr MakeBar( int id1, int id2 ) {
	if ( id1 == 1 &amp;&amp; id2 == 1 )
		return BarPtr( new( Bar&lt;Foo1, Foo1&gt; ) );
	else if ( id1 == 1 &amp;&amp; id2 == 2 )
		return BarPtr( new( Bar&lt;Foo1, Foo2&gt; ) );
	else if ( id1 == 1 &amp;&amp; id2 == 3 )
		return BarPtr( new( Bar&lt;Foo1, Foo3&gt; ) );
	else if ( id1 == 2 &amp;&amp; id2 == 1 )
		return BarPtr( new( Bar&lt;Foo2, Foo1&gt; ) );
	else if ( id1 == 2 &amp;&amp; id2 == 2 )
		return BarPtr( new( Bar&lt;Foo2, Foo2&gt; ) );
	else if ( id1 == 2 &amp;&amp; id2 == 3 )
		return BarPtr( new( Bar&lt;Foo2, Foo3&gt; ) );
	else if ( id1 == 3 &amp;&amp; id2 == 1 )
		return BarPtr( new( Bar&lt;Foo3, Foo1&gt; ) );
	else if ( id1 == 3 &amp;&amp; id2 == 2 )
		return BarPtr( new( Bar&lt;Foo3, Foo2&gt; ) );
	else if ( id1 == 3 &amp;&amp; id2 == 3 )
		return BarPtr( new( Bar&lt;Foo3, Foo3&gt; ) );
	return BarPtr();
}

int main() {
	int userInput1( 2 );
	int userInput2( 3 );
	BarPtr ptr( MakeBar( userInput1, userInput2 ) );
}
</code></pre>
<p>Irgendwelche Ideen, wie man das viele Instanziieren des Klassentemplates nicht mehr manuell machen muss?</p>
<p>Gruß<br />
Dobi</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2215344</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2215344</guid><dc:creator><![CDATA[Dobi]]></dc:creator><pubDate>Fri, 25 May 2012 11:30:51 GMT</pubDate></item><item><title><![CDATA[Reply to TMP: Permutationen von Template-Parametern generieren on Fri, 25 May 2012 12:00:14 GMT]]></title><description><![CDATA[<p>Das geht, ich habe allerdings gerade keinen Compiler zur Hand, um eine fertige Lösung zu erstellen (außerdem ist das eine der Aufgaben für PI :p)<br />
Kurz skizziert könnte das ungefähr so aussehen (wobei mir diese Lösung nihct besonders gut gefällt), da ohne Compiler komplett ungetest und wahrscheinlich auch mit einigen Syntaxfehlern:</p>
<pre><code class="language-cpp">template &lt;typename... T&gt;
struct typelist : std::identity&lt;typelist&lt;T...&gt;&gt; {};

template &lt;typename... L&gt;
struct concat_typelists : std::identity&lt;concat_typelists&lt;typename L::type&gt;&gt; {};

template &lt;typename... T, typename... U, typename... L&gt;
struct concat_typelists&lt;typelist&lt;T...&gt;, typelist&lt;U...&gt;, L...&gt; : concat_typelists&lt;typelist&lt;T..., U...&gt;, L...&gt; {};

template &lt;std::size_t... N, typename L&gt;
struct repeat_list;

template &lt;std::size_t... N, typename... T&gt;
struct repeat_list&lt;N, typelist&lt;T...&gt;&gt; : concat_typelists&lt;typelist&lt;T...&gt;, repeat_list&lt;N-1, T...&gt;&gt; {};

template &lt;typename... T&gt;
struct repeat_list&lt;0, typelist&lt;T...&gt;&gt; : typelist&lt;&gt; {};

template &lt;std::size_t... N, typename L&gt;
struct repeat_types;

template &lt;std::size_t... N, typename... T&gt;
struct repeat_types&lt;N, typelist&lt;T...&gt;&gt; : concat_typelists&lt;repeat_list&lt;N, T&gt;...&gt; {};

template &lt;typename T, typename U&gt;
void foo();

template &lt;typename... T, typename... U&gt;
void dispatch_helper(std::size_t i, typelist&lt;T...&gt;, typelist&lt;U...&gt;)
{
    static const void (*foos[])() = { foo&lt;T, U&gt;... };
    return foos[i]();
}

template &lt;typename... T&gt;
void dispatch(std::size_t i, std::size_t j)
{
    using types = typelist&lt;T...&gt;;
    using types_repeated = repeat_types&lt;sizeof...(T), types&gt;;
    using list_repeated = repeat_list&lt;sizeof...(T), types&gt;;
    dispatch_helper(i*sizeof...(T)+j, types_repeated(), list_repeated());
};
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2215362</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2215362</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Fri, 25 May 2012 12:00:14 GMT</pubDate></item><item><title><![CDATA[Reply to TMP: Permutationen von Template-Parametern generieren on Sat, 26 May 2012 10:04:20 GMT]]></title><description><![CDATA[<pre><code class="language-cpp">template &lt;typename... T&gt;
struct typelist : std::identity&lt;typelist&lt;T...&gt;&gt; {};
</code></pre>
<p>Wie funktioniert das ? Warum erbt camper hier von std::identity ??</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2215677</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2215677</guid><dc:creator><![CDATA[pyhax]]></dc:creator><pubDate>Sat, 26 May 2012 10:04:20 GMT</pubDate></item><item><title><![CDATA[Reply to TMP: Permutationen von Template-Parametern generieren on Sat, 26 May 2012 10:13:30 GMT]]></title><description><![CDATA[<p>Das ist ein TMP-Abkürzungs-Trick. std::identity ist äquivalent zu:</p>
<pre><code class="language-cpp">template &lt;typename T&gt;
struct identity
{
    typedef T type;
};
</code></pre>
<p>Da viele TMP-Algorithmen ihr Ergebnis durch ein typedef type herausgeben, lässt sich ein Algorithmus xyz</p>
<pre><code class="language-cpp">template &lt;typename Foo&gt;
struct xyz
{
    typedef Foo type;
};
</code></pre>
<p>kürzer schreiben als</p>
<pre><code class="language-cpp">template &lt;typename Foo&gt;
struct xyz
    : identity&lt;Foo&gt;
{};
</code></pre>
<p>camper lässt nun seine typelist selbst von std::identity erben. Wenn er nun als Ergebnis eine Leere Typliste haben möchte, kann er deshalb nochmal abkürzen und statt</p>
<pre><code class="language-cpp">: identity&lt;typelist&lt;&gt;&gt;
</code></pre>
<p>direkt</p>
<pre><code class="language-cpp">: typelist&lt;&gt;
</code></pre>
<p>schreiben. Sein repeat_list macht davon Gebrauch.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2215678</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2215678</guid><dc:creator><![CDATA[314159265358979__]]></dc:creator><pubDate>Sat, 26 May 2012 10:13:30 GMT</pubDate></item><item><title><![CDATA[Reply to TMP: Permutationen von Template-Parametern generieren on Sat, 26 May 2012 10:16:07 GMT]]></title><description><![CDATA[<p>Pseudo-Edit: Das &quot;Leere&quot; aus dem letzten Satz streichen. Geht natürlich mit allen Typlisten.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2215680</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2215680</guid><dc:creator><![CDATA[314159265358979__]]></dc:creator><pubDate>Sat, 26 May 2012 10:16:07 GMT</pubDate></item><item><title><![CDATA[Reply to TMP: Permutationen von Template-Parametern generieren on Sat, 26 May 2012 10:28:26 GMT]]></title><description><![CDATA[<p>Ok, danke. Ich wusste vorher noch gar nicht, das man mehr als ein Variadic Template Argument haben kann. <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>
]]></description><link>https://www.c-plusplus.net/forum/post/2215685</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2215685</guid><dc:creator><![CDATA[pyhax]]></dc:creator><pubDate>Sat, 26 May 2012 10:28:26 GMT</pubDate></item><item><title><![CDATA[Reply to TMP: Permutationen von Template-Parametern generieren on Sat, 26 May 2012 10:31:46 GMT]]></title><description><![CDATA[<p>Das geht auch nur bei Klassentemplate-Spezialisierungen und Funktionstemplates wo die Parameter deduziert werden können.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2215688</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2215688</guid><dc:creator><![CDATA[314159265358979__]]></dc:creator><pubDate>Sat, 26 May 2012 10:31:46 GMT</pubDate></item><item><title><![CDATA[Reply to TMP: Permutationen von Template-Parametern generieren on Sat, 26 May 2012 10:34:37 GMT]]></title><description><![CDATA[<p>314159265358979__ schrieb:</p>
<blockquote>
<p>Das geht auch nur bei Klassentemplate-Spezialisierungen und Funktionstemplates wo die Parameter deduziert werden können.</p>
</blockquote>
<p>Ja, das habe ich mir auch schon gedacht. Sonst wäre das ja nicht mehr eindeutig.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2215691</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2215691</guid><dc:creator><![CDATA[pyhax]]></dc:creator><pubDate>Sat, 26 May 2012 10:34:37 GMT</pubDate></item><item><title><![CDATA[Reply to TMP: Permutationen von Template-Parametern generieren on Sat, 26 May 2012 20:12:31 GMT]]></title><description><![CDATA[<p>Wow, super, vielen Dank. Jetzt mach ich mich mal ans Verstehen. <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/2215880</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2215880</guid><dc:creator><![CDATA[Dobi]]></dc:creator><pubDate>Sat, 26 May 2012 20:12:31 GMT</pubDate></item><item><title><![CDATA[Reply to TMP: Permutationen von Template-Parametern generieren on Sat, 26 May 2012 21:00:04 GMT]]></title><description><![CDATA[<p>314159265358979__ schrieb:</p>
<blockquote>
<p>Wenn er nun als Ergebnis eine Leere Typliste haben möchte, kann er deshalb nochmal abkürzen und statt</p>
<pre><code class="language-cpp">: identity&lt;typelist&lt;&gt;&gt;
</code></pre>
<p>direkt</p>
<pre><code class="language-cpp">: typelist&lt;&gt;
</code></pre>
<p>schreiben. Sein repeat_list macht davon Gebrauch.</p>
</blockquote>
<p>Wenn ich das jetzt richtig verstehe, heißt das, dass eine Klasse von sich selbst ableiten kann? o.O</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2215888</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2215888</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Sat, 26 May 2012 21:00:04 GMT</pubDate></item><item><title><![CDATA[Reply to TMP: Permutationen von Template-Parametern generieren on Sun, 27 May 2012 01:35:37 GMT]]></title><description><![CDATA[<p>Hier die bereinigte Version.</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;typeinfo&gt;

template &lt;typename T, typename U&gt;
void foo()
{
    std::cout &lt;&lt; typeid(T).name() &lt;&lt; '\t' &lt;&lt; typeid(U).name() &lt;&lt; '\n';
}

template &lt;typename T&gt; struct identity { using type = T; };

template &lt;typename... T&gt;
struct typelist : identity&lt;typelist&lt;T...&gt;&gt; {};

template &lt;typename... L&gt;
struct concat_typelists : concat_typelists&lt;typename L::type...&gt; {};

template &lt;typename... T, typename... U, typename... L&gt;
struct concat_typelists&lt;typelist&lt;T...&gt;, typelist&lt;U...&gt;, L...&gt; : concat_typelists&lt;typelist&lt;T..., U...&gt;, L...&gt; {};

template &lt;typename... T&gt;
struct concat_typelists&lt;typelist&lt;T...&gt;&gt; : typelist&lt;T...&gt; {};

template &lt;std::size_t N, typename L&gt;
struct repeat_list;

template &lt;std::size_t N, typename... T&gt;
struct repeat_list&lt;N, typelist&lt;T...&gt;&gt; : concat_typelists&lt;typelist&lt;T...&gt;, repeat_list&lt;N-1, typelist&lt;T...&gt;&gt;&gt; {};

template &lt;typename... T&gt;
struct repeat_list&lt;0, typelist&lt;T...&gt;&gt; : typelist&lt;&gt; {};

template &lt;std::size_t N, typename L&gt;
struct repeat_types : repeat_types&lt;N, typename L::type&gt; {};

template &lt;std::size_t N, typename... T&gt;
struct repeat_types&lt;N, typelist&lt;T...&gt;&gt; : concat_typelists&lt;repeat_list&lt;N, typelist&lt;T&gt;&gt;...&gt; {};

template &lt;typename... T, typename... U&gt;
void dispatch_helper(std::size_t i, typelist&lt;T...&gt;, typelist&lt;U...&gt;)
{
    static void (*const foos[])() = { foo&lt;T, U&gt;... };
    return foos[i]();
}

template &lt;typename... T&gt;
void dispatch(std::size_t i, std::size_t j)
{
    using types = typelist&lt;T...&gt;;
    using types_repeated = repeat_types&lt;sizeof...(T), types&gt;;
    using list_repeated = repeat_list&lt;sizeof...(T), types&gt;;
    dispatch_helper(i*sizeof...(T)+j, types_repeated(), list_repeated());
};

struct Foo {};
struct Bar {};
struct Baz {};

int main(int argc, char** argv)
{
    if ( argc &gt;= 2 )
        dispatch&lt;Foo,Bar,Baz&gt;(std::stoul(argv[1]), std::stoul(argv[2]));
}
</code></pre>
<p>TMP-Code leidet häufig darunter, dass eine Menge syntaktischer Lärm erzeugt wird. Die Auswertung von Metafunktionen erfolgt üblicherweise durch die Verwendung des in der Funktion enthaltenen typedefs type. Innerhalb von templates führt das schnell zu typename Foo::type-Orgien.<br />
Unter Beachtung zweier Regeln lässt sich das weitgehend vermeiden: die typenames ...::type stehen zwar noch da, aber nicht mehr an einer interessanten Stelle; sondern in der Definition des Primärtemplates, das andernfalls undefiniert bliebe.<br />
1. Jedes Template, das eigentlich keine Funktion darstellt, erbt von identity, enhält also ein typedef auf sich selbst und ist damit eine Metafunktion, die sich selbst zurückgibt.<br />
2. Jede andere Metafunktion erbt von ihrem Ergebnis.</p>
<p>Auf diese Weise kann dann auch typename ::type an Stellen wie in Zeilen 50-53 vermieden werden. Der Funktionsaufruf funktioniert, weil hierfür eine besondere (und relativ selten gebrauchte) Deduktionsregel existiert, die es erlaubt, eine Basisklasse zu deduzieren, wenn die Deduktion andernfalls fehlschlagen würde.</p>
<p>std::identity ist leider wieder aus dem Standard entfernt worden <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/2215918</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2215918</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sun, 27 May 2012 01:35:37 GMT</pubDate></item><item><title><![CDATA[Reply to TMP: Permutationen von Template-Parametern generieren on Sun, 27 May 2012 06:59:17 GMT]]></title><description><![CDATA[<p>Hacker schrieb:</p>
<blockquote>
<p>Wenn ich das jetzt richtig verstehe, heißt das, dass eine Klasse von sich selbst ableiten kann? o.O</p>
</blockquote>
<p>Nein. Aber du darfst eine Klasse als Template-Parameter der Basisklasse verwenden. Das nennt man dann CRTP.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2215931</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2215931</guid><dc:creator><![CDATA[314159265358979__]]></dc:creator><pubDate>Sun, 27 May 2012 06:59:17 GMT</pubDate></item><item><title><![CDATA[Reply to TMP: Permutationen von Template-Parametern generieren on Sun, 27 May 2012 10:31:45 GMT]]></title><description><![CDATA[<p>314159265358979__ schrieb:</p>
<blockquote>
<p>Hacker schrieb:</p>
<blockquote>
<p>Wenn ich das jetzt richtig verstehe, heißt das, dass eine Klasse von sich selbst ableiten kann? o.O</p>
</blockquote>
<p>Nein. Aber du darfst eine Klasse als Template-Parameter der Basisklasse verwenden. Das nennt man dann CRTP.</p>
</blockquote>
<p>Das kenn ich schon längst, aner hier meintest du doch es wär die vereinfachte Version.. die ohne CRTP.</p>
<p>Edit:</p>
<pre><code class="language-cpp">template &lt;typename... T&gt;
struct typelist : std::identity&lt;typelist&lt;T...&gt;&gt; {};
</code></pre>
<p>Das geht natürlich. Das ist CRTP. Das..</p>
<pre><code class="language-cpp">template &lt;typename... T&gt;
struct typelist : typelist&lt;&gt;{};
</code></pre>
<p>Geht doch nicht? Obwohl es natürlich verschiedene Klassen sind.. der Konstruktor bswp. bleibt gleich, oder? Und auch der Compiler spuckt entsprechende Fehlermeldungen aus (na nicht die, die ich grade meine, aber z. B. dass <code>typelist</code> unvollständig ist)...</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2215963</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2215963</guid><dc:creator><![CDATA[[[global:guest]]]]></dc:creator><pubDate>Sun, 27 May 2012 10:31:45 GMT</pubDate></item></channel></rss>