Templates

Templates sind ein Mittel der "generischen" Programmierung. C++ unterscheidet Funktions-Templates und Klassen-Templates. Template heißt eigentlich Zeichenschablone. Templates sind Vorlagen oder Vorschriften, die dem Compiler mitteilen, wie eine Funktion oder Klasse generiert werden soll.

 


Funktionstemplates 


Beispiel für ein Funktions-Template, das den kleineren von zwei Werten zurückgeben soll:

#include <iostream>
using namespace std;

template <typename T>
T minimum( T val1, T val2 )
{
   return ( ( val1 < val2 ) ? val1 : val2 );
}

template <typename T>
T maximum( T val1, T val2 )
{
   return ( ( val1 > val2 ) ? val1 : val2 );
}

int main()

  string a("Hans"), b("Karl");
  double c=1.2345, d=1.3456;
  cout<<minimum(a,b)<<" "<<minimum(c,d)<<endl;
  cout<<maximum(a,b)<<" "<<maximum(c,d)<<endl;
}


Klassentemplates 

Hier folgt ein Beispiel mit einem allgemeinen "Würfel", der verschiedene Klassen zur Erzeugung der Zufallszahl verwendet. Hierbei ist die entscheidende Stelle die folgende:

template< class T >     // Template-Klasse !!!
class Wuerfel
{
  //...
  const unsigned maxrandom_;
  T zahlengenerator_;   // Template-Typ als Attribut

 

Das komplette Programm:

#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
#include <conio.h>

class Random_aus_Stdlib_geklaut
{
  private:
    unsigned seed_;
    int random()
    {
      // so funktioniert rand():
      return ((( seed_ = seed_ * 214013L + 2531011L ) >> 16 ) & 0x7fff );
    }
  public:
    Random_aus_Stdlib_geklaut(){ seed_ = static_cast<unsigned>(time(NULL)); }
    Random_aus_Stdlib_geklaut( unsigned seed ) { seed_ = seed; }
    int getNum(){ return random(); }
};

class RandomStdlib // verwendet rand()
{
  private:
    const unsigned int seed_;
  public:
    RandomStdlib():seed_( static_cast<unsigned>(time(NULL)) ){}
    int getNum() const
    {
      static bool seed_flag = 0;
      if( !seed_flag )
      {
        srand( seed_ );
        seed_flag = true;
      }
      return rand();
    }
};

class RandomTestEqual // Test auf Gleichverteilung
{
  private:
    int num_;
  public:
    RandomTestEqual() : num_(RAND_MAX - 1){};
    int getNum()
    {
      ++num_;
      if( num_ >= RAND_MAX )
          num_ = 0;
      return num_;
    }
};

template< class T_Generator > // Template-Klasse !!!
class Wuerfel
{
  private:
    const unsigned maxzahl_;
    const unsigned maxrandom_;
    T_Generator zahlengenerator_; // Template-Typ als Attribut

  public:
    Wuerfel( unsigned maxzahl ) :
    maxzahl_(maxzahl), maxrandom_(RAND_MAX-(RAND_MAX%maxzahl)) {}

    unsigned wuerfelt()
    {
      unsigned r;
      do{ r = zahlengenerator_.getNum(); }
      while ( r >= maxrandom_ );
      return ( r % maxzahl_ + 1 );
    }
};

int main()
{
  const unsigned long long Serie    =        3;
  const unsigned long long Versuche = 30000000;
  const unsigned limit              =      200;
  const unsigned moeglichkeiten     =        6;

  Wuerfel<RandomTestEqual>           w0a( moeglichkeiten );
  Wuerfel<RandomTestEqual>           w0b( 2 );
  Wuerfel<RandomStdlib>              w1a( moeglichkeiten );
  Wuerfel<RandomStdlib>              w1b( 2 );
  Wuerfel<Random_aus_Stdlib_geklaut> w2a( moeglichkeiten );
  Wuerfel<Random_aus_Stdlib_geklaut> w2b( 2 );

  unsigned long long H[moeglichkeiten+1];

  for( unsigned long long i=1; i<Serie+1; ++i )
  {
    for( unsigned j=0; j<moeglichkeiten+1; ++j )
         H[j] = 0;
    for( unsigned long long k=1; k<Versuche+1; ++k )
    {
         unsigned wurf = w1a.wuerfelt();   // hier wird gewürfelt !!!!

         if( Versuche<limit )
             std::cout << wurf << " ";
         ++H[wurf];
    }

    for( unsigned c=1; c<moeglichkeiten+1; ++c )
    {
        std::cout << std::endl << c << ": " << H[c] << " " << std::setprecision(7)
                  << 100 * static_cast<float>(H[c]) / Versuche << " %";
        H[0] += H[c]; 
    }
    std::cout << std::endl << "Wuerfe insgesamt: " << H[0] << std::endl << std::endl;
  }
getch();
}
 

Eine besonders raffinierte und effiziente Technik des Template-Klassen-Prinzips bietet im C++-Standard die STL.

Siehe auch: http://de.wikipedia.org/wiki/C%2B%2B-Metaprogrammierung#Potenzberechnung_mit_Hilfe_von_Metatemplates