Metaprogramowanie

Metaprogramowanie oparte o szablony C++

TMP w C++

Nazywanie obiektów

Funkcje w TMP

Kod warunkowy

Rekursja zamiast pętli

Instrukcja warunkowa

Czasami zachodzi potrzeba dobrania typu zmiennej w zależności od pewnego sprawdzalnego na etapie kompilacji warunku. Osiągnąć to możemy poprzez meta if.
template <bool Condition, typename TrueResult, typename FalseResult>
struct IF;
template <typename TrueResult, typename FalseResult>
struct IF<true, TrueResult, FalseResult>
{
  typedef TrueResult result;
};
template <typename TrueResult, typename FalseResult>
struct IF<false, TrueResult, FalseResult>
{
  typedef FalseResult result;
};
Teraz możemy dokonać wyboru w programie:
int main(){
  typedef unsigned long uint32;
  typedef unsigned long long uint64;

  IF<true, int, void*>::result number(3);
  IF<false, int, void*>::result pointer(&number);

  typedef IF<(sizeof(void *) > sizeof(uint32)), uint64, uint32>::result  integral_ptr_t;
  integral_ptr_t converted_pointer = reinterpret_cast<integral_ptr_t>(pointer);
}

Obliczanie stałych na etapie kompilacji

Oto inne obok silni przykłady obliczania stałych na etapie kompilacji (CTE - Compile Time Evaluation)

Rozwijanie pętli sumującej

Rozważmy kod:
template<int N>
struct SUM{
  static inline double EXEC(double v[]){
    return v[N-1]+SUM<N-1>::EXEC(v);
  }
};
template<>
struct SUM<1>{
  static inline double EXEC(double v[]){
    return v[0];
  }
};
Wywołanie
s=SUM<4>::EXEC(a)
jest semantycznie równoważne wykonaniu pętli
double s=0;
for(int i=0;i<N;++i) s+=a[i];
jednak wykona się szybciej, bo skompiluje się tak jak kod:
s=a[3]+a[2]+a[1]+a[0];

Rozwijanie pętli piszącej

Rozważmy kod:
template<int i>
class LOOP{
  public:
    static inline void EXEC(){
      cout << "A-" << i << " ";
            LOOP< i-1 >::EXEC();
       cout << "B-" << i << " ";
    }
};
template<>
class LOOP<0>{
  public:
    static inline void EXEC(){
      cout << "A-" << 0;
      cout << "\n";
      cout << "B-" << 0;
    }
};
Wywołanie
s=LOOP<8>::EXEC(a)
zostanie w trakcie kompilacji rozwinięte do
cout << "A-" << 8 << " ";
cout << "A-" << 7 << " ";
...
cout << "A-" << 0;
cout << "\n";
cout << "B-" << 0;
...
cout << "B-" << 7 << " ";
cout << "B-" << 8 << " ";

Pożytki z metaprogramowania