
Queue<int> qi, of a class from the generic class template definition is called template instantiation.Queue qs; // Error: which template argument type?
// the return type and two parameters are instantiations of Queue
extern Queue< complex<double> >
foo( Queue< complex<double> > &, Queue< complex<double> > & );
// pointer to member function of an instantiation of Queue
bool (Queue<double>::*pmf)() = 0;
// explicit cast of 0 to a pointer to an instantiation of Queue
Queue<char*> *pqc = static_cast< Queue<char*>* > ( 0 );
template<class T>
class Queue {};
template<class T>
void bar( Queue<T>&, Queue<double>& ){}
void foo( Queue<int>& ){}
int main() {
Queue<int> qi;
Queue<double> qd;
bar<int>(qi, qd);
foo(qi);
return 0;
}
class Matrix;
Matrix* pm; // ok
void inverse(Matrix&); // ok
Queue<int> becomes known to the compiler at the point (Queue<int> qi;), called the point of instantiation of the class Queue<int>. Similarly, if a pointer or reference refers to a class template instantiation, only when examining the object to which such a pointer or reference refers is the class template instantiated.
void foo( Queue<int> &qi )
{
// instantiatioan point of Queue<double>
Queue<double> qd;
Queue<int> *pqi = &qi;
// instantiatioan point of Queue<int>
pqi->add( 255 );
}
QueueItem<int> is only instantiated when these members are dereferenced in the member functions of class Queue<int>.
template <class Type>
class Queue {
public:
// ...
private:
QueueItem<Type> *front;
QueueItem<Type> *back;
};
template <class Type>
class QueueItem {
public:
QueueItem( Type ); // bad design choice
};
template <class Type>
class QueueItem {
// potentially inefficient
QueueItem( const Type &t ) {
item = t; next = 0;
}
};
template <class Type>
class QueueItem {
// item initialized in constructor member initialization list
QueueItem( const Type &t ): item(t) { next = 0; }
};
See Consider pass by value for copyable parameters that are cheap to move and always copied. for details.
template <int size> Buf{ ... };
template <int *ptr> class BufPtr { ... };
int size_val = 1024;
const int c_size_val = 1024;
Buf< 1024 > buf0; // ok
Buf< c_size_val > buf1; // ok
Buf< sizeof(size_val) > buf2; // ok: sizeof(int)
BufPtr< &size_val > bp0; // ok
template <int *ptr> class BufPtr { ... };
// error: template argument cannot be evaluated at compile-time
BufPtr< new int[24] > bp;
template <int size> Buf{ ... };
int size_val = 1024;
Buf< size_val > buf3;
template <int *ptr> class BufPtr { ... };
int array[10];
BufPtr< array > bpObj; // array-to-pointer conversion
template <int hi, int wid> class Screen { ... };
const short shi = 40;
const short swi = 132;
Screen< shi, swi > bpObj2; // promotion from short to int
template <lunsigned int size> Buf{ ... };
Buf<l 1024 > bObj; // conversion from int to unsigned int
template <int *ptr>
class BufPtr { ... };
// error: 0 is of type int
// implicit conversion to the null pointer value using
// an implicit pointer conversion is not applied
BufPtr< 0 > nil;