A template is a parameterised function for creating a generic class or function. Using templates means that one function or class can be used with several different types of data, without having to recode specific versions for each data type. A function template starts with the keyword template followed by template parameter(s) enclosed in angled brackets followed by the function declaration. The general form of a template function definition is −
template <class T>
T someFunction(T arg)
{
.....
}
The generic parameter name can then be substituted for the normal variable type within the preceding function. The compiler will then generate different versions of that function corresponding to the data type within the function call
The following worked example uses a function template to return the maximum of two different values using 3 different value parameter types −
#include <iostream>
#include <string>
using namespace std;
//creates template with parameter type myTemplate
template <typename myTemplate>
//template function accepts two parameter types a and b
myTemplate Max (myTemplate a, myTemplate b)
{ if (a>b)
{ return a; }
return b;
}
int main ()
{
int i = 20;
int j = 10;
//calls template function and generates compile time function for int values
cout << "Max(i, j): " << Max(i, j) << endl;
double f1 = 13.5;
double f2 = 20.7;
//calls template function and generates compile time function for double values
cout << "Max(f1, f2): " << Max(f1, f2) << endl;
string s1 = "a";
string s2 = "b";
//calls template function and generates compile time function for char values
cout << "Max(s1, s2): " << Max(s1, s2) << endl;
return 0;
}
You can define more than one generic data type in the template statement by using a comma-separated list. The following worked example accepts two template parameter types and calls the template function using a char and int parameter followed by an int and char parameter.
#include <iostream>
using namespace std;
//creates template with 2 different parameter types
template <class type1, class type2>
void myfunc(type1 x, type2 y)
{
cout << x << ' ' << y << '\n';
}
int main()
{
//calls template function with parameter types char and int
myfunc("5x2=", 10);
//calls template function with parameter types int and char
myfunc(10, "=9+1");
return 0;
}
It is possible to mix standard parameters with generic type parameters in a template function. In the following worked example a template function functionX accepts a template parameter and a standard parameter. The standard parameter is set with a default value of 0. The function is first called by specifying only the template parameter type and then called by specifying the template parameter type and standard parameter.
#include <iostream>
using namespace std;
template <typename X>
//creates template function with template parameter and standard parameter with default value 0
void FunctionX(X value1,int value2=0)
{
if (value2!=NULL)
{
cout << value1 << " ";
cout << value2 ;
}
else
{
cout << "float value=" << value1 << endl;
}
}
int main()
{
float b=4.33;
// calls template function using only template parameter.
FunctionX(b);
// calls template function using template parameter and standard parameter.
FunctionX( "float value cast to int =",b);
return 0;
}
To set a default template parameter type in the above code using the following template declaration-
template <typename x=int>
Template functions can be overloaded. In the following example, the template function T is overloaded with a function that accepts int parameter values. When the function is called with int values the overloaded function is called. All other parameter values invoke the generic template function.
#include <iostream>
using namespace std;
template <class X>
void T(X a, X b)
{
cout << "Inside template T.\n";
cout << a << b;
cout << endl;
}
// This overrides the generic version of t for ints.
void T(int &a, int &b)
{
cout << "Inside overloaded function\n";
cout << a << "X" << b <<"=" << a*b;
}
int main()
{
int i=10,
j=20;
char *word1="hello ";
char *word2="word ";
T(word1, word2); // calls generic template t()
T(i, j); // calls overloaded function t()
return 0;
}
Variadic functions can be used to write functions that accept an arbitrary number of arguments. Variable templates or variadic templates have been part of C++ since C++14, released in 2014
#include <iostream>
using namespace std;
template <typename T>
double sum(T t) { //base case
return t;
}
template <typename T,typename... Rest>//recursive case
double sum(T t,Rest... rest)
{
return t + sum(rest...);
}
int main()
{
double dTotal = 0;
dTotal=sum (33, 3.14, 4.56, 1.1111,44,55);
cout << "dResult = " << dTotal << endl;
return 0;
}
The variadic function requires a ‘base’ case and a ‘recursive’ case. In the above example, the compiler finds and executes the sum function for each argument in turn and then finally executes the base function i.e. the function which has no argument. The declaration of a variadic function uses ellipsis as the last parameter. The sizeof...() is an operator that can return the number of template arguments passed in a call to a variable template. In the above code cout<< sizeof...(rest) would return the number of calls left after each iteration. Programmers using variable templates avoid can avoid the repetitive effort of creating code thus making the shorter and simpler to maintain.
It is also possible to write classes that utilise templates. A class template will have members that use template parameters as types. In the example below, the class template is instantiated with both an int and a char and the maximum value is returned.
// class templates
#include <iostream>
using namespace std;
template <class T>
class compare {
T x, y;//declare template class variables
public:
compare (T firstp, T secondp)
{x=firstp; y=secondp;}//set initial value of class variables
T getmax ();
};
template <class T>
T compare<T>::getmax ()
{
T retval;
retval = x>y? x : y;//return highest class variable
return retval;
}
int main () {
compare <int> templateobject (10, 22);//instantiate class template
cout << templateobject.getmax();
compare <char> templateobjectc ('e', 'z');//instantiate class template
cout << templateobjectc.getmax();
return 0;
}
Last Updated: 15 September 2022