<?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[[C++11] Templates&#x2F;constexpr und Rekursion.]]></title><description><![CDATA[<p>Hallo,</p>
<p>es ist ja hinlänglich bekannt wie man mittels Templates Schleifen durch Rekursion realisiert. Fast jeder kennt sicherlich das Beispiel der Berechnung der Fakultät.<br />
Durch <code>constexpr</code> kann man sich nun ein haufen Tipparbeit sparen und einfach schreiben</p>
<pre><code>constexpr int fak (int N)
{
  return N &lt; 2 ? 1 : N * fak(N-1);
}
</code></pre>
<p>Leider kann man solche Funktion nur durch integrale Konstanten parametrisieren, während man Templates durch Typen und Templates parametrisieren kann. Also hab ich mir gedacht, warum nicht so:</p>
<pre><code>template &lt;int N&gt;
constexpr int fak ()
{
  return N &lt; 2 ? 1 : N * fak&lt;N-1&gt; ();
}

int main()
{
  fak&lt;10&gt; ();
  return 0;
}
</code></pre>
<p>Mein Compiler (gcc-4.8, gcc-4.7) scheint das aber nicht zu verstehen, zumindest versucht er die Funktion für alle möglichen Werte von N zu instanzieren und schreit mich an mit</p>
<pre><code>Fehler: Instanziierungstiefe für Templates überschreitet Höchstwert ...
</code></pre>
<p>Jetzt habe ich mich halt gefragt: Habe ich einen Denkfehler? Liegt es am Compiler? Was sagt der Standard dazu?<br />
Ich finde das jedenfalls sehr schade. Nur als kleines Bsp:</p>
<pre><code>template &lt;typename Type, Type...&gt; // meinetwegen auch tupel oder sonstwas
struct compiletime_vector
{
  typedef Type value_type;
};

template &lt;typename Type, Type T0, Type... TN&gt;
struct compiletime_vector &lt;Type, T0, TN...&gt;
{
  typedef Type value_type;

  static constexpr Type                   head = T0;
  typedef compiletime_vector&lt;Type, TN...&gt; tail;
};

template &lt;typename Vec, int N&gt;
constexpr typename Vec::value_type get_element ()
{
  return N == 0 ? Vec::head : get_element&lt;typename Vec::tail, N-1&gt; ();
}

int main()
{
    typedef compiletime_vector &lt;int, 10, 20, 30, 40, 50&gt; vector;

    get_element&lt;vector, 2&gt; (); // fails

    return 0;
}
</code></pre>
<p>(mir ist klar das ich die get Methode auch in ein struct packen und durch Spezialisiereung die Rekursion beenden kann)</p>
<p>Erbitte Diskussion <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/topic/311265/c-11-templates-constexpr-und-rekursion</link><generator>RSS for Node</generator><lastBuildDate>Mon, 03 Aug 2026 16:43:28 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/311265.rss" rel="self" type="application/rss+xml"/><pubDate>Sat, 01 Dec 2012 10:20:43 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to [C++11] Templates&#x2F;constexpr und Rekursion. on Sat, 01 Dec 2012 10:43:48 GMT]]></title><description><![CDATA[<p>Hallo,</p>
<p>es ist ja hinlänglich bekannt wie man mittels Templates Schleifen durch Rekursion realisiert. Fast jeder kennt sicherlich das Beispiel der Berechnung der Fakultät.<br />
Durch <code>constexpr</code> kann man sich nun ein haufen Tipparbeit sparen und einfach schreiben</p>
<pre><code>constexpr int fak (int N)
{
  return N &lt; 2 ? 1 : N * fak(N-1);
}
</code></pre>
<p>Leider kann man solche Funktion nur durch integrale Konstanten parametrisieren, während man Templates durch Typen und Templates parametrisieren kann. Also hab ich mir gedacht, warum nicht so:</p>
<pre><code>template &lt;int N&gt;
constexpr int fak ()
{
  return N &lt; 2 ? 1 : N * fak&lt;N-1&gt; ();
}

int main()
{
  fak&lt;10&gt; ();
  return 0;
}
</code></pre>
<p>Mein Compiler (gcc-4.8, gcc-4.7) scheint das aber nicht zu verstehen, zumindest versucht er die Funktion für alle möglichen Werte von N zu instanzieren und schreit mich an mit</p>
<pre><code>Fehler: Instanziierungstiefe für Templates überschreitet Höchstwert ...
</code></pre>
<p>Jetzt habe ich mich halt gefragt: Habe ich einen Denkfehler? Liegt es am Compiler? Was sagt der Standard dazu?<br />
Ich finde das jedenfalls sehr schade. Nur als kleines Bsp:</p>
<pre><code>template &lt;typename Type, Type...&gt; // meinetwegen auch tupel oder sonstwas
struct compiletime_vector
{
  typedef Type value_type;
};

template &lt;typename Type, Type T0, Type... TN&gt;
struct compiletime_vector &lt;Type, T0, TN...&gt;
{
  typedef Type value_type;

  static constexpr Type                   head = T0;
  typedef compiletime_vector&lt;Type, TN...&gt; tail;
};

template &lt;typename Vec, int N&gt;
constexpr typename Vec::value_type get_element ()
{
  return N == 0 ? Vec::head : get_element&lt;typename Vec::tail, N-1&gt; ();
}

int main()
{
    typedef compiletime_vector &lt;int, 10, 20, 30, 40, 50&gt; vector;

    get_element&lt;vector, 2&gt; (); // fails

    return 0;
}
</code></pre>
<p>(mir ist klar das ich die get Methode auch in ein struct packen und durch Spezialisiereung die Rekursion beenden kann)</p>
<p>Erbitte Diskussion <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2276277</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2276277</guid><dc:creator><![CDATA[ScottZhang]]></dc:creator><pubDate>Sat, 01 Dec 2012 10:43:48 GMT</pubDate></item><item><title><![CDATA[Reply to [C++11] Templates&#x2F;constexpr und Rekursion. on Sat, 01 Dec 2012 11:10:37 GMT]]></title><description><![CDATA[<p>ScottZhang schrieb:</p>
<blockquote>
<p>Habe ich einen Denkfehler?</p>
</blockquote>
<p>Das (ein wenig). Die Regeln sind im Grunde die Gleichen wie in C++03, und gerade weil jetzt auch constexpr-Funktionen zur Verfügung stehen, gibt es keinen Grund, an diesen Regeln etwas zu ändern.</p>
<p>n3337 schrieb:</p>
<blockquote>
<p>14.7.1 Implicit instantiation [temp.inst]<br />
[...]<br />
3 Unless a function template specialization has been explicitly instantiated or explicitly specialized, <strong>the function<br />
template specialization is implicitly instantiated when the specialization is referenced in a context that<br />
requires a function definition to exist.</strong> Unless a call is to a function template explicit specialization or to a<br />
member function of an explicitly specialized class template, a default argument for a function template or a<br />
member function of a class template is implicitly instantiated when the function is called in a context that<br />
requires the value of the default argument.</p>
<p>3.2 One definition rule [basic.def.odr]<br />
[...]<br />
3 <strong>Every program shall contain exactly one definition of every non-inline function or variable that is odr-used<br />
in that program; no diagnostic required.</strong> The definition can appear explicitly in the program, it can be found<br />
in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and<br />
12.8). An inline function shall be defined in every translation unit in which it is odr-used.</p>
<p>2 <strong>An expression is potentially evaluated unless it is an unevaluated operand (Clause 5) or a subexpression<br />
thereof.</strong> A variable whose name appears as a potentially-evaluated expression is odr-used unless it is an<br />
object that satisfies the requirements for appearing in a constant expression (5.19) and the lvalue-to-rvalue<br />
conversion (4.1) is immediately applied. this is odr-used if it appears as a potentially-evaluated expression<br />
(including as the result of the implicit transformation in the body of a non-static member function (9.3.1)).<br />
A virtual member function is odr-used if it is not pure. <strong>A non-overloaded function whose name appears<br />
as a potentially-evaluated expression or a member of a set of candidate functions, if selected by overload<br />
resolution when referred to from a potentially-evaluated expression, is odr-used, unless it is a pure virtual<br />
function and its name is not explicitly qualified.</strong> [ Note: This covers calls to named functions (5.2.2), operator<br />
overloading (Clause 13), user-defined conversions (12.3.2), allocation function for placement new (5.3.4), as<br />
well as non-default initialization (8.5). A copy constructor or move constructor is odr-used even if the call<br />
is actually elided by the implementation. —end note ] An allocation or deallocation function for a class is<br />
odr-used by a new expression appearing in a potentially-evaluated expression as specified in 5.3.4 and 12.5.<br />
A deallocation function for a class is odr-used by a delete expression appearing in a potentially-evaluated<br />
expression as specified in 5.3.5 and 12.5. A non-placement allocation or deallocation function for a class is<br />
odr-used by the definition of a constructor of that class. A non-placement deallocation function for a class is<br />
odr-used by the definition of the destructor of that class, or by being selected by the lookup at the point of<br />
definition of a virtual destructor (12.4).26 A copy-assignment function for a class is odr-used by an implicitlydefined<br />
copy-assignment function for another class as specified in 12.8. A move-assignment function for a<br />
class is odr-used by an implicitly-defined move-assignment function for another class as specified in 12.8. A<br />
default constructor for a class is odr-used by default initialization or value initialization as specified in 8.5.<br />
A constructor for a class is odr-used as specified in 8.5. A destructor for a class is odr-used as specified<br />
in 12.4.</p>
<p>5 Expressions [expr]<br />
[...]<br />
7 <strong>In some contexts, unevaluated operands appear (5.2.8, 5.3.3, 5.3.7, 7.1.6.2).</strong> An unevaluated operand is not<br />
evaluated. [ Note: In an unevaluated operand, a non-static class member may be named (5.1) and naming<br />
of objects or functions does not, by itself, require that a definition be provided (3.2). —end note ]</p>
<p><strong>5.2.8 Type identification [expr.typeid]<br />
5.3.3 Sizeof [expr.sizeof]<br />
5.3.7 noexcept operator [expr.unary.noexcept]<br />
7.1.6.2 Simple type specifiers [dcl.type.simple]</strong> &lt;-- hier geht es in diesem Zusammenhang um decltype</p>
</blockquote>
<p>Die Frage, ob ein bestimmter Teilausdruck ausgewertet wird oder nicht, hat erst einmal nichts damit zu tun, ob darin enthaltene Templatespezialisierungen auch instantiiert werden müssen, es sei denn, es handelt sich um eine der o.g. Ausnahmen (typeid,sizeof,noexcept,decltype).</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2276280</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2276280</guid><dc:creator><![CDATA[camper]]></dc:creator><pubDate>Sat, 01 Dec 2012 11:10:37 GMT</pubDate></item><item><title><![CDATA[Reply to [C++11] Templates&#x2F;constexpr und Rekursion. on Sun, 02 Dec 2012 10:24:20 GMT]]></title><description><![CDATA[<p>Erstmal danke camper für die Mühe, das rauszusuchen. Ich gebs zu ich war einfach zu faul dazu :). Aber ich bin kein Programmierer, bei mir hätte das Tage oder Wochen in anspruch genommen ...</p>
<p>Dann bleibt die Frage warum das Template instanziiert werden muss (für N&lt;2).<br />
Denn das der Ausdruck</p>
<pre><code>N &lt; 2 ? die : das;
</code></pre>
<p>nicht immer vollständig ausgewertet wird ist offensichtlich.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2276475</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2276475</guid><dc:creator><![CDATA[ScottZhang]]></dc:creator><pubDate>Sun, 02 Dec 2012 10:24:20 GMT</pubDate></item><item><title><![CDATA[Reply to [C++11] Templates&#x2F;constexpr und Rekursion. on Sun, 02 Dec 2012 10:33:57 GMT]]></title><description><![CDATA[<pre><code>template &lt;unsigned short N&gt; //
constexpr unsigned long long fak ()
{
  return N * fak&lt;N-1&gt; ();
}

template &lt;&gt; constexpr unsigned long long fak&lt;1&gt; () { return 1; }
template &lt;&gt; constexpr unsigned long long fak&lt;0&gt; () { return 1; }

#include &lt;iostream&gt;

int main()
{
  std::cout &lt;&lt; fak&lt;10&gt; ();
}
</code></pre>
<p>Wieso den Konditionsoperator? Man kann doch gleich spezialisieren...<br />
(Ich habe die Typen ein wenig angepasst)</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2276477</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2276477</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Sun, 02 Dec 2012 10:33:57 GMT</pubDate></item><item><title><![CDATA[Reply to [C++11] Templates&#x2F;constexpr und Rekursion. on Sun, 02 Dec 2012 10:37:01 GMT]]></title><description><![CDATA[<p>Partielle spezialisierung geht aber nicht ...</p>
<p>Es geht mir garnicht um alternetive Lösungen, die sind mir bekannt.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2276478</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2276478</guid><dc:creator><![CDATA[ScottZhang]]></dc:creator><pubDate>Sun, 02 Dec 2012 10:37:01 GMT</pubDate></item><item><title><![CDATA[Reply to [C++11] Templates&#x2F;constexpr und Rekursion. on Sun, 02 Dec 2012 10:45:14 GMT]]></title><description><![CDATA[<p>ScottZhang schrieb:</p>
<blockquote>
<p>Partielle spezialisierung geht aber nicht ...</p>
</blockquote>
<p>Wie meinst du das? Dass das funktioniert ist doch klar.</p>
<p>ScottZhang schrieb:</p>
<blockquote>
<p>Es geht mir garnicht um alternetive Lösungen, die sind mir bekannt.</p>
</blockquote>
<p>Ach, ok ^^</p>
<p>Hilft dir das weiter:</p>
<pre><code>template &lt;unsigned char N&gt;
constexpr unsigned long long fak ()
{
    return N &lt; 2 ? 1 : N * fak&lt;N-1&gt; ();
}

int main()
{
      fak&lt;10&gt; ();
}
</code></pre>
<p>Das funktioniert.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2276480</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2276480</guid><dc:creator><![CDATA[Sone]]></dc:creator><pubDate>Sun, 02 Dec 2012 10:45:14 GMT</pubDate></item><item><title><![CDATA[Reply to [C++11] Templates&#x2F;constexpr und Rekursion. on Sun, 02 Dec 2012 10:52:34 GMT]]></title><description><![CDATA[<p>Ich meine sowas</p>
<pre><code>template &lt;typename Dawas, size_t Lauf&gt;
consexpr bla_type tu_was () 
{
  return mach_was_mit ( tu_was&lt;Dawas, Lauf-1&gt; () );
}
</code></pre>
<p>In dem Falle bräuchtes du ne partielle Spezialisierung von Funktionen was nach meiner Kenntnis nicht erlaubt ist</p>
<p>Sone schrieb:</p>
<blockquote>
<pre><code>template &lt;unsigned char N&gt;
constexpr unsigned long long fak ()
{
    return N &lt; 2 ? 1 : N * fak&lt;N-1&gt; ();
}

int main()
{
      fak&lt;10&gt; ();
}
</code></pre>
<p>Das funktioniert.</p>
</blockquote>
<p>Ja das würde gehen, entspricht aber nicht dem Sachverhalt und ist getrickst <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2276482</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2276482</guid><dc:creator><![CDATA[ScottZhang]]></dc:creator><pubDate>Sun, 02 Dec 2012 10:52:34 GMT</pubDate></item><item><title><![CDATA[Reply to [C++11] Templates&#x2F;constexpr und Rekursion. on Sun, 02 Dec 2012 14:22:52 GMT]]></title><description><![CDATA[<p><s>Seit C++11 ist das übrigens erlaubt wenn ich mich richtig erinnere, die ganz ganz neueste VS 2012 Beta sollte das sogar erlauben. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /></s> Falsch erinnert.<br />
Falls du das Feature noch nicht hast, geben structs + statische Methoden Abhilfe.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2276519</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2276519</guid><dc:creator><![CDATA[cooky451]]></dc:creator><pubDate>Sun, 02 Dec 2012 14:22:52 GMT</pubDate></item></channel></rss>