template<class T> class Array {
  T* v;
  int sz;
public:
  explicit Array(int);
  T& operator[](int);
  T& elem(int i) { return v[i]; }
};
The prefix template<class T>
specifies that a template is being declared and that a
type-name
T
may be used in the declaration.
template<class T1, class T2> struct A {
  void f1();
  void f2();
};
template<class T2, class T1> void A<T2,T1>::f1() { }    // OK
template<class T2, class T1> void A<T1,T2>::f2() { }    // error
template<class ... Types> struct B {
  void f3();
  void f4();
};
template<class ... Types> void B<Types ...>::f3() { }    // OK
template<class ... Types> void B<Types>::f4() { }        // error
 — end example
template<class T> class Array {
  T* v;
  int sz;
public:
  explicit Array(int);
  T& operator[](int);
  T& elem(int i) { return v[i]; }
};
template<class T> T& Array<T>::operator[](int i) {
  if (i<0 || sz<=i) error("Array: range error");
  return v[i];
} — end exampleArray<int> v1(20); Array<dcomplex> v2(30); v1[3] = 7; // Array<int>::operator[]() v2[3] = dcomplex(7,8); // Array<dcomplex>::operator[]()— end example
template<class T> struct A {
  class B;
};
A<int>::B* b1;                  // OK: requires A to be defined but not A::B
template<class T> class A<T>::B { };
A<int>::B  b2;                  // OK: requires A::B to be defined
 — end note
template<class T> class X {
  static T s;
};
template<class T> T X<T>::s = 0;
struct limits {
  template<class T>
    static const T min;         // declaration
};
template<class T>
  const T limits::min = { };    // definition
 — end example
template <class T> struct A {
  static int i[];
};
template <class T> int A<T>::i[4];              // 4 elements
template <> int A<int>::i[] = { 1 };            // OK: 1 element
 — end example