Templated Functions


By Alex Allain
C++ templates can be used both for classes and for functions in C++. Templated functions are actually a bit easier to use than templated classes, as the compiler can often deduce the desired type from the function's argument list.



The syntax for declaring a templated function is similar to that for a templated class:
template <class type> type func_name(type arg1, ...);
For instance, to declare a templated function to add two values together, you could use the following syntax:
template <class type> type add(type a, type b)
{
    return a + b;
}
Now, when you actually use the add function, you can simply treat it like any other function because the desired type is also the type given for the arguments. This means that upon compiling the code, the compiler will know what type is desired:
int x = add(1, 2);
will correctly deduce that "type" should be int. This would be the equivalent of saying:
int x = add<int>(1, 2);
where the template is explicitly instantiated by giving the type as a template parameter.

On the other hand, type inference of this sort isn't always possible because it's not always feasible to guess the desired types from the arguments to the function. For instance, if you wanted a function that performed some kind of cast on the arguments, you might have a template with multiple parameters:
template <class type1, class type2> type2 cast(type1 x)
{
    return (type2)x;
}
Using this function without specifying the correct type for type2 would be impossible. On the other hand, it is possible to take advantage of some type inference if the template parameters are correctly ordered. In particular, if the first argument must be specified and the second deduced, it is only necessary to specify the first, and the second parameter can be deduced.

For instance, given the following declaration
template <class rettype, class argtype> rettype cast(argtype x)
{
    return (rettype)x;
}
this function call specifies everything that is necessary to allow the compiler deduce the correct type:
cast<double>(10);
which will cast an int to a double. Note that arguments to be deduced must always follow arguments to be specified. (This is similar to the way that default arguments to functions work.)

You might wonder why you cannot use type inference for classes in C++. The problem is that it would be a much more complex process with classes, especially as constructors may have multiple versions that take different numbers of parameters, and not all of the necessary template parameters may be used in any given constructor.

Templated Classes with Templated Functions

It is also possible to have a templated class that has a member function that is itself a template, separate from the class template. For instance,
template <class type> class TClass
{
    // constructors, etc
    
    template <class type2> type2 myFunc(type2 arg);
};
The function myFunc is a templated function inside of a templated class, and when you actually define the function, you must respect this by using the template keyword twice:
template <class type>  // For the class
    template <class type2>  // For the function
    type2 TClass<type>::myFunc(type2 arg)
    {
        // code
    }
The following attempt to combine the two is wrong and will not work:
// bad code!
template <class type, class type2> type2 TClass<type>::myFunc(type2 arg)
{
    // ...
}
because it suggests that the template is entirely the class template and not a function template at all.