Template Metaprogramming Patterns

martin-adams-522797-unsplash

SFINAE – Substitution Failure is Not An Error

Template meta programming is fun. Lot of simple algorithms can be done at compile time and in very powerful way. The code uses a template meta-programming pattern called as SFINAE – Substitution failure is not an error.

Following are three examples for common problems like Fibonacci, Factorial and GCD calculations using SFINAE.

#include <iostream>

// find fibonacci using template meta-programming
template <long long N>
struct fibonacci{
  static constexpr long long value = fibonacci<N-1>::value + fibonacci<N-2>::value;
};

template<>
struct fibonacci<1>{
  static constexpr long long value = 1;
};

template<>
struct fibonacci<0>{
  static constexpr long long value = 0;
};

// end code for fibonacci
// -------------------------------------------------------------------------------------------
// find gcd using template meta programming
template<unsigned M, unsigned N>
struct gcd{
  static constexpr auto value = gcd<N,M%N>::value;
};

template<unsigned M>
struct gcd<M,0>{
  static_assert(M!=0);
  static constexpr auto value = M;
};
// -------------------------------------------------------------------------------------------
// factorial using template meta-programming
template<long long N>
struct factorial{
  static constexpr long long value = N*(factorial<N-1>::value);
};

template<>
struct factorial<0>{
  static constexpr long long value = 1;
};

int main(){
  std::cout << gcd<15,5>::value << '\n'; // 5
  std::cout << fibonacci<80>::value << '\n'; // 23416728348467685
  std::cout << factorial<20>::value << '\n'; // 2432902008176640000
}

More information about SINAF

 

CRTP – Curiously Recurring Template Pattern

The CRTP pattern was discovered  by an accident. There is another name for this pattern,  “Static Polymorphism”.The base class is generally templatized class and derived class is subclassed from base class with type as templatized class. The reason this is called as CRTP is because a method from derived class is called from base class statically.  The definition is rather complicated but the code should clear it.

#include <iostream>

struct Exchange{
  std::string name;
};

template <typename T>
struct Order{
  int transact(Exchange * exchange, size_t quantity){
    return static_cast<T *>(this)->transact(quantity);
  }
};

struct BuyOrder: Order<BuyOrder>{
  int transact(Exchange * exchange, size_t quantity){
    buy();
    return quantity;
  }

  void buy(){
    // code for buy goes here..
  }
};

struct SellOrder: Order<SellOrder>{
  int transact(Exchange * exchange, size_t quantity){
    sell();
    return quantity;
  }

  void sell(){
    // code for sell goes here..
  }
};

int main(){
  Exchange e;
  BuyOrder bo;
  bo.transact(e, 100);
  SellOrder so;
  so.transact(e, 100);
}