Blog der Heimetli Software AG

Beispielprogramm zur Template-Rekursion in C++

/******************************************************************************/
/*                                                                            */
/*  Compile time recursion in C++                                             */
/*  =============================                                             */
/*                                                                            */
/*  V2.00   09-APR-2013   P. Tellenbach   Completely Rewritten for g++ 4.7.2  */
/*                                                                            */
/******************************************************************************/
#include <iostream>

using namespace std ;

template<const int n, bool recurse = true>
class Count
{
 public:
   static inline int print()
   {
      Count< n - 1, (n > 1) >::print() ;

      cout << n << " " ;

      return n ;
   }
} ;

template<const int n>
class Count<n,false>
{
 public:
   static inline int print()
   {
      cout << n << " " ;

      return n ;
   }
} ;

int main( )
{
 return Count< 5 >::print() == 0 ;
}

Der Compiler erzeugt während der Kompilation des Codes rekursiv die Klassen Count<5,true>, Count<4,true>, Count<3,true>, Count<2,true>, Count<1,true> und Count<0,false>.

Der Code benutzt dazu zwei häufig benutzte Tricks der Template-Programmierer:

Default-Argumente

Das allgemeine Template für die Klasse Count hat ein Argument recurse, das gar nie benutzt wird. Es wird nur gebraucht um die beiden Templates für Count auseinander zu halten.

Beim ersten Aufruf aus der Funktion main wird nur der Parameter n angegeben, was bewirkt dass der Default-Wert von true eingesetzt wird.

Während der Intanzierung des Templates wird ein weiteres gefunden, das wieder instanziert wird ...

Partielle Spezialisierung

Das zweite Template für die gleiche Klasse wird instanziert wenn der zweite Parameter false ist. In unserem Beispiel ist das der Fall wenn n bei der Rekursion kleiner als 2 ist.

Das zweite Template dient also dazu, die Rekursion zu beenden.

Was passiert, wenn die Rekursion nicht endet ?

Natürlich war der Code nicht auf Anhieb korrekt, was die Grenzen des Compilers testete. g++ 4.7.2 brach nach 900 Instanzierungen die Kompilation ab, bot aber an, die Grenze mit einer Option zu erhöhen ;-)

Wozu dient das == 0 ?

Der Aufruf von Count<5>::print() gibt 5 zurück. Das würde dem aufrufenden Programm einen Fehler signalisieren.

Der Vergleich mit 0 ergibt false, was von C++ als int mit dem Wert 0 betrachtet wird. Dieses 0 übergibt main an den Parent-Prozess, der es als erfolgreiche Programmausführung interpretiert.

Selber ausprobieren

Sie können den Code herunterladen und damit herumspielen.