[1] Use templates to express algorithms that apply to many argument types; 
  [2] Use templates to express containers; 
  [3] Provide specializations for containers of pointers to minimize code size; 
  [4] Always declare the general form of a template before specializations; 
  [5] Declare a specialization before its use; 
  [6] Minimize a template definition’s dependence on its instantiation contexts;
  [7] Define every specialization you declare; 
  [8] Consider if a template needs specializations for C-style strings and arrays; 
  [9] Parameterize with a policy object; 
  [10] Use specialization and overloading to provide a single interface to implementations of the same concept for different types; 
  [11] Provide a simple interface for simple cases and use overloading and default arguments to express less common cases; 
  [12] Debug concrete examples before generalizing to a template; 

  [13] Remember to e x p o r t template definitions that need to be accessible from other translation units; 

  [14] Separately compile large templates and templates with nontrivial context dependencies; 
  [15] Use templates to express conversions but define those conversions very carefully;
  [16] Where necessary, constrain template arguments using a constraint() member function;
  [17] Use explicit instantiation to minimize compile time and link time;
  [18] Prefer a template over derived classes when runtime efficiency is at a premium;
  [19] Prefer derived classes over a template if adding new variants without recompilation is important;
  [20] Prefer a template over derived classes when no common base can be defined; 

  [21] Prefer a template over derived classes when built-in types and structures with compatibility constraints are important;