Function Templates In C++

We looked at a very straightforward class template last time, which should have given you the confidence to get started in creating your own template classes.

Now, to round off this introduction to C++ templates, we’ll just have a quick look at function templates, and talk a little more about the workings behind template source code.

As usual, we’ll start with the code, and then dissect it below in order to understand what is going on.

Here’s an example program:

#include <iostream>
#include <string>

using namespace std;

template<class T>
void printdata(T); //function declaration

int main()
{
    int x = 34567;
    string tmp = "hello";
    double y = 3.162;

    printdata(x);
    printdata(tmp);
    printdata(y);

    return 0;
}

template<class T>void printdata(T t) //function definition
{
    cout << t << endl;
}

Okay, so if you run this code, it will output:

34567
hello
3.162

If we look at what’s going on, we’ve got one function (print data). Anything we pass to it, it prints out.

Unlike a regular function, we don’t have to specify a particular argument type to pass in. If we couldn’t use template functions, we’d have to declare three individual functions that took a defined parameter each time (int, string, double). Instead we use the template syntax and tell the function that we will pass a type “T” called “t”.

This follows the familiar format of normal function arguments – e.g. saying we will pass a type int called x, or a type string called tmp – except we don’t have to know anything about the type T other than it will contain some form of data.

The template function means we can focus on the process, rather than the data itself.

Going to back to what Bjarne said (which I quoted in my previous post): Templates provide direct support for generic programming.

They are not about specifics, they are all about processing data without getting hung up on what that data is.

For comparison, this is what the code above would look like if we didn’t use a template function:

#include <iostream>
#include <string>

using namespace std;

//function definitions
void printdata(int);
void printdata(string);
void printdata(double);

int main()
{
    int x = 34567;
    string tmp = "hello";
    double y = 3.162;

    printdata(x);
    printdata(tmp);
    printdata(y);

    return 0;
}

//function declarations
void printdata(int number)
{
    cout << number << endl;
}

void printdata(string letters)
{
    cout << letters << endl;
}

void printdata(double fraction)
{
    cout << fraction << endl;
}

Can you see how we have to specify each individual function?

Not only that, but we’d have to add more code for every new data type that we wanted to use. The template version though, never needs more than one single declaration and definition.

That’s cool, but what does the compiler do with template source code? Doesn’t it just create all those functions anyway?

That’s exactly right, the compiler does create the functions, but the important thing is that there is no maintenance of this code, no potential for copy and paste errors, and no need to keep adjusting/adding functions every time your data type changes.

Also, the compiler will only create source for datatypes that are used.

This is important, so I’ll explain it again:

In the template example at the top, we call the template function with three different data types – int, string and double. The template function however, could also take another type, such as a char, or even a user defined class, or enum, or anything. However, the compiler won’t create functions for every single possible data type that you might use – how could it even know them all? Instead it only creates source code for the actual data types that are called in your program. If, for example, we deleted the call to print the string data, the compiler would no longer create a function to deal with string data.

This is also true for class templates – the compiler will only create source code once for each particular class type that you instantiate in your code.

So, in fact, template functions are efficient in that they only generate as much code as is needed for your program to execute successfully, no more, no less.