<?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[Klassentemplate matchen]]></title><description><![CDATA[<p>Hallo da,<br />
ich bin jetzt etwas länger raus aus dem Geschäft, und habe nun ein Problem mit templates, bei dem ihr mir vielleicht helfen könnt.<br />
Problemstellung ist folgende:</p>
<pre><code class="language-cpp">unsigned int mask = stm::detail::type_or_default&lt; stm::fsmc::args::width&lt;8&gt;, int, float, double, stm::fsmc::args::width&lt;16&gt; &gt;::type::value;
</code></pre>
<p>Also type_or_default soll den ersten Parameter &quot;zurückliefern&quot;, oder in der folgenden Liste eine andere &quot;Instanz&quot; desselben Templates heraussuchen.</p>
<p>Intuitiv habe ich dazu erstmal folgenden Test implementiert:</p>
<pre><code class="language-cpp">template&lt; template&lt; typename... &gt; class Argument, typename... Parameters1, typename... Parameters2 &gt;
std::true_type same_argument(Argument&lt;Parameters1...&gt;, Argument&lt; Parameters2... &gt;);

template&lt; template&lt; typename... &gt; class Argument, typename... Parameters1, class B &gt;
std::false_type same_argument(Argument&lt;Parameters1...&gt;, B);

...
std::is_same&lt; decltype(same_argument(Default(), Arg0())), std::true_type &gt;::value
...
</code></pre>
<p>Aber das funktioniert natürlich nur bei Klassentemplates, die ausschließlich Typen als Parameter haben. Kann man das auch irgendwie für Templates mit integralen Parametern gangbar machen, wie in dem ersten Beispiel mit Integern?</p>
<p>Viele Grüße!</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/327321/klassentemplate-matchen</link><generator>RSS for Node</generator><lastBuildDate>Thu, 09 Jul 2026 12:06:37 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/327321.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 04 Aug 2014 10:04:04 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to Klassentemplate matchen on Mon, 04 Aug 2014 10:04:04 GMT]]></title><description><![CDATA[<p>Hallo da,<br />
ich bin jetzt etwas länger raus aus dem Geschäft, und habe nun ein Problem mit templates, bei dem ihr mir vielleicht helfen könnt.<br />
Problemstellung ist folgende:</p>
<pre><code class="language-cpp">unsigned int mask = stm::detail::type_or_default&lt; stm::fsmc::args::width&lt;8&gt;, int, float, double, stm::fsmc::args::width&lt;16&gt; &gt;::type::value;
</code></pre>
<p>Also type_or_default soll den ersten Parameter &quot;zurückliefern&quot;, oder in der folgenden Liste eine andere &quot;Instanz&quot; desselben Templates heraussuchen.</p>
<p>Intuitiv habe ich dazu erstmal folgenden Test implementiert:</p>
<pre><code class="language-cpp">template&lt; template&lt; typename... &gt; class Argument, typename... Parameters1, typename... Parameters2 &gt;
std::true_type same_argument(Argument&lt;Parameters1...&gt;, Argument&lt; Parameters2... &gt;);

template&lt; template&lt; typename... &gt; class Argument, typename... Parameters1, class B &gt;
std::false_type same_argument(Argument&lt;Parameters1...&gt;, B);

...
std::is_same&lt; decltype(same_argument(Default(), Arg0())), std::true_type &gt;::value
...
</code></pre>
<p>Aber das funktioniert natürlich nur bei Klassentemplates, die ausschließlich Typen als Parameter haben. Kann man das auch irgendwie für Templates mit integralen Parametern gangbar machen, wie in dem ersten Beispiel mit Integern?</p>
<p>Viele Grüße!</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2411897</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2411897</guid><dc:creator><![CDATA[decimad]]></dc:creator><pubDate>Mon, 04 Aug 2014 10:04:04 GMT</pubDate></item><item><title><![CDATA[Reply to Klassentemplate matchen on Mon, 04 Aug 2014 10:53:51 GMT]]></title><description><![CDATA[<blockquote>
<p>Kann man das auch irgendwie für Templates mit integralen Parametern gangbar machen, wie in dem ersten Beispiel mit Integern?</p>
</blockquote>
<p>Nein. Ist auch ein doofes Problem mit C++-Templates auf das ich schon mehrmals gestoßen bin.</p>
<blockquote>
<p>oder in der folgenden Liste eine andere &quot;Instanz&quot; desselben Templates heraussuchen.</p>
</blockquote>
<p>Du meinst Spezialisierung.</p>
<p>Was allerdings eine relativ einfache Lösung darstellt ist ein <code>match</code> -Template zu nehmen, welches prüft ob ein Typ eine Spezialisierung deines Templates ist - damit musst du nicht entsprechend partiell Spezialisieren sondern kannst per <code>conditional</code> die Spezialisierungen herausfiltern:</p>
<pre><code>#include &lt;type_traits&gt;

template &lt;unsigned V&gt;
struct width : std::integral_constant&lt;unsigned, V&gt; {};

// Dieses Template muss bereitgestellt werden
template &lt;typename&gt; struct is_width_spec : std::false_type {};
template &lt;unsigned u&gt; struct is_width_spec&lt;width&lt;u&gt;&gt; : std::true_type {};

/// [...]

template &lt;template&lt;typename&gt; class, typename, typename...&gt;
struct type_or_default;

template &lt;template&lt;typename&gt; class spec_check, typename Def, typename First, typename... Args&gt;
struct type_or_default&lt;spec_check, Def, First, Args...&gt; :
	std::conditional&lt; spec_check&lt;First&gt;::value, First,
	                  typename type_or_default&lt;spec_check, Def, Args...&gt;::type &gt; {};

template &lt;template&lt;typename&gt; class spec_check, typename Def&gt;
struct type_or_default&lt;spec_check, Def&gt;
{
	using type = Def;
};

#include &lt;iostream&gt;

int main()
{
	unsigned int mask = type_or_default&lt; is_width_spec, width&lt;8&gt;, int, float, double, width&lt;16&gt; &gt;::type::value;
	std::cout &lt;&lt; mask;
}
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2411911</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2411911</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Mon, 04 Aug 2014 10:53:51 GMT</pubDate></item><item><title><![CDATA[Reply to Klassentemplate matchen on Mon, 04 Aug 2014 11:02:44 GMT]]></title><description><![CDATA[<p>Hallo Nexus!<br />
Danke für die Antwort!</p>
<p>Okay, ich war dann auch pragmatisch und habe das jetzt etwas umständlich so gelöst:</p>
<pre><code class="language-cpp">struct tag_tag {};

template&lt; typename T &gt;
struct tag : public tag_tag
{
};

template&lt; template&lt; typename... &gt; class Argument, typename... Parameters1, typename... Parameters2 &gt;
std::true_type same_argument(Argument&lt;Parameters1...&gt;, Argument&lt; Parameters2... &gt;);

template&lt; typename T &gt;
std::true_type same_argument(const tag&lt;T&gt;&amp;, const tag&lt;T&gt;&amp;);

template&lt; typename A, typename B &gt;
struct convertible_to_tag : public std::conditional&lt; std::is_base_of&lt; tag_tag, A &gt;::value &amp;&amp; std::is_base_of&lt; tag_tag, B &gt;::value, std::true_type, std::false_type &gt;::type
		{};

template&lt; typename A, typename B &gt;
std::false_type same_argument(A, B, typename std::enable_if&lt; !convertible_to_tag&lt;A,B&gt;::value, int &gt;::type some = 1 );
</code></pre>
<p>Somit kann man jetzt solche Teile mit integralen Parametern mit einer ausgesuchten Spezialisierung von sich selbst taggen und braucht keine extra Klassen mehr:</p>
<pre><code class="language-cpp">template&lt; int Width &gt;
struct width : public detail::tag&lt; width&lt;8&gt; &gt;
{
    static_assert(Width == 8 || Width == 16, &quot;&quot;);
    enum {
        value = Width
    };
};

// ...

unsigned int mask = stm::detail::type_or_default&lt; stm::fsmc::args::width&lt;8&gt;, int, float, double, stm::fsmc::args::width&lt;16&gt; &gt;::type::value;
// mask == 16
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2411915</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2411915</guid><dc:creator><![CDATA[decimad]]></dc:creator><pubDate>Mon, 04 Aug 2014 11:02:44 GMT</pubDate></item><item><title><![CDATA[Reply to Klassentemplate matchen on Mon, 04 Aug 2014 11:55:30 GMT]]></title><description><![CDATA[<blockquote>
<p>Hallo Nexus!</p>
</blockquote>
<p>Hallo Volkard!</p>
<pre><code>template&lt; typename T &gt;
std::true_type same_argument(const tag&lt;T&gt;&amp;, const tag&lt;T&gt;&amp;);
</code></pre>
<p>Brauchst hier keine Referenz.</p>
<pre><code>template&lt; int Width &gt;
struct width : public detail::tag&lt; width&lt;8&gt; &gt;
{
    static_assert(Width == 8 || Width == 16, &quot;&quot;);
    enum {
        value = Width
    };
};
</code></pre>
<ul>
<li>Die Konstante value kannst du einfach per <code>static const auto value = Width;</code> deklarieren. Wozu ein Enumerator?</li>
<li>Warum erlaubst du nur 8 oder 16? Falls du nur Zweierpotenzen erlauben willst, nimm <code>Width &amp; Width-1 == 0 &amp;&amp; Width != 0</code> als Bedingung (und natürlich einen vorzeichenlosen Typ für den Parameter).<br />
So sieht das etwas merkwürdig aus. Soll das noch erweitert werden?</li>
<li>Die Basisklasse sollte wohl eher <code>tag&lt;width&lt;Width&gt;&gt;</code> (bzw. <code>tag&lt;width&gt;</code> ) sein, oder?<br />
Ach ne, die Basisklasse muss ja dieselbe sein. Dann aber lieber ein zufälliger Typ wie - <code>void</code> . Also die base-clause zu <code>: detail::tag&lt;void&gt;</code> verkürzen. Dann stellt sich aber die Frage warum du überhaupt noch ein Template tag hast - Aha, <strong>um verschiedene Templates zu unterscheiden!</strong></li>
</ul>
<p>Vom letzten Punkt aus kann man sowas schreiben:</p>
<pre><code>struct tag_tag {};

template&lt; int T &gt;
struct tag : tag_tag {};

#define UNIQUE_TAG tag&lt;__COUNTER__&gt; // predefined macro in GCC, Clang and MSVC

template &lt;int i&gt;
std::true_type same_argument(tag&lt;i&gt;, tag&lt;i&gt;);

// [...]

template&lt; int Width &gt;
struct width : UNIQUE_TAG
{
    // ...
</code></pre>
<p>Jetzt schreibst du <code>UNIQUE_TAG</code> als Basisklasse für jedes Template hin und bekommst dann für jedes Template eine <code>tag</code> -Basisklasse.<br />
_____________________________________________________________________________________________________________________________________________________________________________</p>
<pre><code>std::conditional&lt; std::is_base_of&lt; tag_tag, A &gt;::value &amp;&amp; std::is_base_of&lt; tag_tag, B &gt;::value, std::true_type, std::false_type &gt;::type
</code></pre>
<p>Lässt sich ganz einfach umformen zu</p>
<pre><code>std::integral_constant&lt;bool, std::is_base_of&lt; tag_tag, A &gt;::value &amp;&amp; std::is_base_of&lt; tag_tag, B &gt;::value&gt;
</code></pre>
<p>Ist aber natürlich nicht hübsch; warum für genau zwei?</p>
<p>Lieber allgemein bleiben:</p>
<pre><code>template &lt;template&lt;typename&gt; class check, typename F, typename... T&gt;
struct all_of : std::integral_constant&lt;bool, check&lt;F&gt;::value &amp;&amp; all_of&lt;check, T...&gt;::value&gt; {};

template &lt;template&lt;typename&gt; class check, typename F&gt;
struct all_of&lt;check, F&gt; : std::integral_constant&lt;bool, check&lt;F&gt;::value&gt; {};

template &lt;typename A&gt;
using convertible_to_tag = std::is_base_of&lt;tag_tag, A&gt;;
</code></pre>
<p><img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/27a1.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--right_arrow"
      title=":arrow_right:"
      alt="➡"
    /></p>
<pre><code>template&lt; typename A, typename B &gt;
typename std::enable_if&lt;!all_of&lt;convertible_to_tag, A, B&gt;::value, std::false_type&gt;::type same_argument(A, B);
</code></pre>
]]></description><link>https://www.c-plusplus.net/forum/post/2411935</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2411935</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Mon, 04 Aug 2014 11:55:30 GMT</pubDate></item><item><title><![CDATA[Reply to Klassentemplate matchen on Mon, 04 Aug 2014 12:15:36 GMT]]></title><description><![CDATA[<p>Sorry Arcoth, ich war halt ausgelastet im Kopf!</p>
<p>Auf Makros verzichte ich gerne!<br />
Ich brauche nicht mehr als 2 Argumente bei dem Vergleich, weil ich eben immer nur 2 vergleiche.<br />
Die Spezialwerte sind da, weil das eine c++-Bibliothek für ein bestimmtes Hardwareteil werden soll, das eben nur 8 oder 16 Bit Busbreite unterstützt. Initialisierungsaufrufe sollen so möglichst &quot;eingängig&quot; sein, und im Gegensatz zu der mitgelieferten C-Bibliothek auf Operationen mit Konstanten hinauslaufen (keine Ahnung, wie die da sowas ausliefern konnten...).<br />
Die static-const Sache ermöglicht ja das Adresse-nehmen (und damit eine Vergrößerung der Binary), dachte ich, daher habe ich mir irgendwann angewöhnt, trotzdem immer enum zu verwenden.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2411941</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2411941</guid><dc:creator><![CDATA[decimad]]></dc:creator><pubDate>Mon, 04 Aug 2014 12:15:36 GMT</pubDate></item><item><title><![CDATA[Reply to Klassentemplate matchen on Mon, 04 Aug 2014 12:29:23 GMT]]></title><description><![CDATA[<blockquote>
<p>Die static-const Sache ermöglicht ja das Adresse-nehmen (und damit eine Vergrößerung der Binary), dachte ich</p>
</blockquote>
<p>Ist aber nicht korrekt. Du definierst die Variable nirgends, daher existiert sie zur Laufzeit gar nicht - und du kannst ihre Adresse nicht nehmen, denn das würde einen odr-use darstellen und zu einem Linkerfehler führen.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2411946</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2411946</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Mon, 04 Aug 2014 12:29:23 GMT</pubDate></item><item><title><![CDATA[Reply to Klassentemplate matchen on Mon, 04 Aug 2014 13:58:40 GMT]]></title><description><![CDATA[<p>Arcoth schrieb:</p>
<blockquote>
<p>Jetzt schreibst du <code>UNIQUE_TAG</code> als Basisklasse für jedes Template hin und bekommst dann für jedes Template eine <code>tag</code> -Basisklasse.</p>
</blockquote>
<p>Wie war das nochmal mit Templatedefinitionen in verschiedenen ÜEs und der ODR?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2411969</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2411969</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Mon, 04 Aug 2014 13:58:40 GMT</pubDate></item><item><title><![CDATA[Reply to Klassentemplate matchen on Mon, 04 Aug 2014 14:13:44 GMT]]></title><description><![CDATA[<p>camper schrieb:</p>
<blockquote>
<p>Arcoth schrieb:</p>
<blockquote>
<p>Jetzt schreibst du <code>UNIQUE_TAG</code> als Basisklasse für jedes Template hin und bekommst dann für jedes Template eine <code>tag</code> -Basisklasse.</p>
</blockquote>
<p>Wie war das nochmal mit Templatedefinitionen in verschiedenen ÜEs und der ODR?</p>
</blockquote>
<p>Ganz vergessen, dann kann man das so nicht verwenden.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2411970</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2411970</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Mon, 04 Aug 2014 14:13:44 GMT</pubDate></item><item><title><![CDATA[Reply to Klassentemplate matchen on Mon, 04 Aug 2014 15:22:28 GMT]]></title><description><![CDATA[<p>Arcoth schrieb:</p>
<blockquote>
<blockquote>
<p>Hallo Nexus!</p>
</blockquote>
<p>Hallo Volkard!</p>
<pre><code>template&lt; typename T &gt;
std::true_type same_argument(const tag&lt;T&gt;&amp;, const tag&lt;T&gt;&amp;);
</code></pre>
<p>Brauchst hier keine Referenz.</p>
</blockquote>
<p>Da hätte ich auch keine gemacht. Du scheinst mich mit jemandem zu verwechseln.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2411977</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2411977</guid><dc:creator><![CDATA[volkard]]></dc:creator><pubDate>Mon, 04 Aug 2014 15:22:28 GMT</pubDate></item><item><title><![CDATA[Reply to Klassentemplate matchen on Mon, 04 Aug 2014 18:33:12 GMT]]></title><description><![CDATA[<blockquote>
<p>Da hätte ich auch keine gemacht</p>
</blockquote>
<p>Hätt' ich nicht erwartet! Muss ich mich vor dir in Acht nehmen?</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2411999</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2411999</guid><dc:creator><![CDATA[Columbo]]></dc:creator><pubDate>Mon, 04 Aug 2014 18:33:12 GMT</pubDate></item></channel></rss>