Wednesday, November 18, 2009

Template Functions




I l@ve RuBoard


Template Functions


A stand-alone nonmember function can be defined as a template; the syntax is similar to the syntax of template class member functions.





template <class T>
void swap(T& x, T& y)
{ T a = x; x = y; y = a; }



When the function needs a prototype, it also contains the template parameter list with each class keyword followed by a parameter.





template <class T> void swap(T& x, T& y);



Both the definition and the prototype (forward declaration) start with the template keyword followed by the formal parameter list in angle brackets; each formal parameter consists of the keyword class followed by a programmer-defined identifier. The keyword class and the identifier are separated by commas. The identifier must occur only once in the parameter list.





template <class T, class T> // this is illegal
void swap(T& x, T& y)
{ T a = x; x = y; y = a; }



Each type parameter must be used in the parameter list of the template function. If the type parameter is not present in the parameter list, the compiler flags it as a syntax error





template <class T>
int isEmpty(void); // compile-time error for global function



Similar to non-template functions, template functions can be declared extern,
inline, or static; the specifier (if any) follows the template list of formal parameters and precedes the function return type.





template <class T>
inline void swap(T& x, T& y) // inline function
{ T a = x; x = y; y = a; }



When the compiler processes the definition of a template function, it does not generate object code. Instantiation of a template function takes place at its invocation. Since each actual parameter is mentioned in the parameter list by name, and its type is known to the compiler, there is no need to specify the actual argument type at the template invocation:





int a=5, b=10; double c=3.0, d=4.0;
swap(a,b); // instantiation for integers
swap(c,d); // instantiation for double



Since compiler knows the types of the actual arguments a and b for the first call and c and d for the second call, it generates code for swap(int&,int&) and swap(double&,double&).



A return value is not considered for parameter matching; conversions can be done as needed. However, implicit conversions are not used for template arguments. If the compiler cannot decide which function to generate to match arguments exactly, it is a syntax error.





swap(a,c); // syntax error: no exact match



Overloading of template functions is allowed provided they can be distinguished by the types of the actual arguments or by the number of arguments.





template <class T>
inline void swap(T& x, T& y, T& z) // three parameters
{ T a = x; x = y; y = z; z = a; }



This function can be distinguished from the swap() function with two parameters.





int a=5, b=10, c=20;
swap(a,b); swap(a,b,c);



Template functions can be specialized to adjust their behavior for specific types. For example, character arrays cannot be swapped as integers, and a specialized version must be used. The rules for forming function specializations are the same as for template class specializations. You deplete the template parameter list and move actual types (in angle brackets) between the function name and the parameter list. Here is a specialized function swap().





template < >
inline void swap <char*> (char* x, char* y)
{ char* a = new char[strlen(x)+1];
char* b = new char[strlen(y)+1];
if (b==NULL) { cout << "Out of memory\n"; exit(1); }
strcpy(a,x); strcpy(b,y); // caller must assure space
strcpy(x,b); strcpy(y,a);
delete a; delete b; }



Client code:





char x[20]="Hello!", y[20]="Hi, there!"; int a=5, b=10;
swap(a,b); // general template function is instantiated
swap(x,y); // specialized template function is instantiated



The compiler first searches for a non-template function; if one is found and parameters match exactly, templates are not considered; if more than one non-template alternative matches, it is a syntax error.



If no matching non-template alternative is found, then templates are examined. If there is an exact match and its instantiation already exists, it is used and no new object code is generated; otherwise, the function is instantiated; if more than one match is found, it is an error.



If no matching template function is found, non-template functions are examined using implicit conversions and promotions of arguments.



A template function cannot be called by or be passed as an argument to a non-template function.







I l@ve RuBoard

No comments: