An Idiot's Guide to C++ Templates - Part 1

Prolusion

Most C++ programmers stay away from C++ templates due to their perplexed nature. The excuses against templates:

Hard to learn and adapt.

Compiler errors are vague, and very long.

Not worth the effort.

Admitted that templates are slightly hard to learn, understand, and adapt. Nevertheless, the advantages we gain from using templates would outweigh the negatives. There is
a lot more than generic functions or classes that can be wrapped around templates. I would explicate them.

While C++ templates and STL (Standard Template Library) are siblings, technically. In this article, I would only cover templates at the core level. Next parts of this series would cover more advanced and interesting stuff around templates, and some know-how about STL.

Interestingly, class type ostream (the type of cout object) has multiple overloads for operator << - for all basic data-types. Therefore, same/similar code works for both int and double, and no change is required for our PrintTwice overloads - yes, we just copy-pasted it. Had we used one of printf-functions, the two overloads would look like:

Here the point is not about cout or print to display on console, but about the code - which is absolutely same. This is one of the many situations where we can utilize the groovy feature provided by the C++ language: Templates!

Templates are of two types:

Function Templates

Class Templates

C++ templates is a programming model that allows plugging-in of any data-type to the code (templated code). Without template, you would need to replicate same code all over again and again, for all required data-types. And obviously, as said before, it requires code maintenance.

Anyway, here is the simplifiedPrintTwice, utilizing templates:

void PrintTwice(TYPE data)
{
cout<<"Twice: " << data * 2 << endl;
}

Here, actual type of TYPE would be deduced (determined) by the compiler depending on argument passed to the function. If PrintTwice is called as PrintTwice(144); it would be an int, if you pass 3.14 to this function, TYPE would be deduced as double type.

You might be confused what TYPE is, how the compiler is going to determine that this is a function template. Is TYPE type defined using typedef keyword somewhere?

No, my boy! Here we use the keyword template to let compiler know that we are defining a function template.

tells the compiler that this is a function-template. The actual meaning of TYPE would be deduced by compiler depending on the argument passed to this function. Here, the name, TYPE is known as template type parameter.

For instance, if we call the function as:

PrintTwice(124);

TYPE would be replaced by compiler as int, and compiler would instantiate this template-function as:

void PrintTwice(int data)
{
cout<<"Twice: " << data * 2 << endl;
}

And, if we call this function as:

PrintTwice(4.5547);

It would instantiate another function as:

void PrintTwice(double data)
{
cout<<"Twice: " << data * 2 << endl;
}

It means, in your program, if you call PrintTwice function with int and double parameter types, two instances of this function would be generated by compiler:

Yes, the code is duplicated. But these two overloads are instantiated by the compiler and not by the programmer. The true benefit is that you need not to do copy-pasting the same code, or to manually maintain the code for different data-types, or to write up a new overload for new data-type that arrives later. You would just provide a template of a function, and rest would be managed by compiler.

It is also true that code size would increase, since there are now two function definitions. The code-size (at binary/assembly level) would almost be same. Effectively, for N number of data-types, N instances of same function (i.e. overloaded functions) would be created. There are advanced compiler/linker level optimizations which can somewhat reduce the code size, if instantiated functions are same, or some part of function body is same. I wouldn't discuss it now.

But, on a positive side, when you manually define N different overloads (say N=10), those N different overloads would be anyway be compiled,linked and packed in binary (the executable). However, with templates, only the required instantiations of function would get into final executable. With templates, the overloaded copies of function might be less than N, and it can be more than N - but exactly the number of required copies - no more no less!

Also, for non-templated implementations, the compiler has to compile all those N copies - since they are in your source-code! When you attach template with a generic function, compiler would compile only for required set of data-types. It basically means the compilation would be faster if number of different data-types is less than N!

It would be a perfectly valid argument, that the compiler/linker would likely do all possible optimizations to remove unused non-template function' implementations from the final image. But, again, do understand that compiler has to compile all those overloads (for syntax checking etc). With templates, the compilation would happen only for required data-types - you can call it as "On demand compilation".

Enough of text-only content for now! You can come back and re-read it again. Let's move ahead.

Now, let's write another function template that would return the twice of given number:

template<typename TYPE>
TYPE Twice(TYPE data)
{
return data * 2;
}

You should have noticed that I used typename, instead of class. No, it is not required to use typename keyword if a function returning something. For template programming, these two keywords are very much the same. There is a historical reason for having two keywords for same purpose, and I hate history.

However, there are instances where you can only use the newer keyword - typename. (When a particular type is defined in another type, and is dependent on some template parameter - Let this discussion be deferred to another part).

Moving ahead. When we call this function as:

cout << Twice(10);
cout << Twice(3.14);
cout << Twice( Twice(55) );

Following set of functions would be generated:

int Twice(int data) {..}
double Twice(double data) {..}

Two things:

In third line of code snipped above, Twice is called twice - the return value/type of first call would be the argument/type of second call. Hence, both calls are of int type (Since argument type TYPE, and return type are same).

If a template function is instantiated for a particular data-type, compiler would re-use the same function' instance - if the function is invoked again for same data-type. It means, irrespective of where, in your code, you invoke the function template with same type - in same function, in different function, or anywhere in another source file (of same project/build).

Let's write up a function template that would return the addition of two numbers:

template<class T>
T Add(T n1, T n2)
{
return n1 + n2;
}

Firstly, I just replaced template-type parameter's name - TYPE with symbol T. In template programming, you would generally use T - but that's a personal choice. You should better use a name that reflects the meaning of type-parameter, and that improves code readability. This symbol can be any name which follows variable naming rules in the C++ language.

Secondly, I re-used the template parameter T - for both of arguments (n1 and n2).

Let's slightly modify Add function, which would store the addition in local variable and then return the calculated value.

Quite explanatory, I used the type parameter T within the function's body. You might ask (you should): "How the compiler would know what is type of result, when it tries to compile/parse the function Add?"

Well, while looking at the body of function template (Add), compiler would not see if T (template type parameter) is correct or not. It would simply check for basic syntax (such as semi-colons, proper usage of keywords, matching braces etc), and would report errors for those basic checks. Again, it depends on compiler to compiler how it handles the template code - but it would not report any errors resulting due to template type parameters.

Just for completeness, I would reiterate, compiler will not check if (currently relevant only for function Add):

T is having a default constructor (so that T result; is valid)

T supports the usage of operator + (so that <code>n1+n2 is valid)

T has an accessible copy/move-constructor (so that return statement succeeds)

Essentially, the compiler would have to compile the template code in two phases: Once for basic syntax checks; and later for each instantiation of function template - where it would perform actual code compilation against the template data-types.

It is perfectly okay if you did not completely understood this two phase compilation process. You would get firm understanding as you read through this tutorial, and then you would come back to read these theory-sessions later!

For the first call of GetAverage, where IntArray is passed, compiler would instantiate this function as:

double GetAverage(int tArray[], int nElements);

And similarly for float. The return type is kept as double since average of numbers would logically fit in double data-type. Note that this is just for this example - the actual data-type that comes under T may be a class, which may not be converted to double.

You should notice that a function template may have template type arguments, along with non-template type arguments. It it not required to have all arguments of a function template to arrive from template types. int nElements is such function argument.

Clearly note and understand that template type-parameter is just T, and not T* or T[]- compilers are smart enough to deduce the type int from an int[] (or int*). In the example given above, I have used T tArray[] as an argument to function template, and actual data-type of T would intelligently be determined from this.

Most often, you would come across and would also require to use initialization like:

T tSum = T();

First thing first, this is not template specific code - this comes under C++ language itself. It essentially means: Call the default constructor for this datatype. For int, it would be:

int tSum = int();

Which effectively initializes the variable with 0. Similarly, for float, it would set this variable to 0.0f. Though not covered yet, if a user defined class type comes from T, it would call the default constructor of that class (If callable, otherwise relevant error). As you can understand that T might be any data-type, we cannot initialize tSum simply with an integer zero (0). In real case, it may be a some string class, which initializes it with empty string ("").

Since the template type T may be any type, it must also have += operator available. As we know, it is available for all basic data types (int, float, char etc.). If actual type (for T), doesn't have += operator available (or any possibility), compiler would raise an error that actual type doesn't have this operator, or any possible conversion.

Similarly, the type T must be able to convert itself to double (see the return statement). I will cover up these nitty-gritties, later. Just for better understanding, I am re-listing the required support from type T (now, only applicable for GetAverage function template):

Must have an accessible default constructor.

Must have += operator callable.

Must be able to convert itself to double (or equivalent).

For GetAverage function template prototype, you may use T* instead of T[], and would mean the same:

template<class T>
GetAverage(T* tArray, int nElements){}

Since the caller would be passing an array (allocated on stack or heap), or an address of a variable of type T. But, as you should be aware, these rules comes under rule-book of C++, and not specifically from template programming!

Moving ahead. Let's ask the actor 'reference' to come into template programming flick. Quite self-explanatory now, you just use T& as a function template argument for the underlying type T:

Which calculates the twice value of argument, and puts into same argument' value. You would call it simply as:

int x = 40;
TwiceIt(x); // Result comes as 80

Note that I used operator *= to get twice of argument tData. You may also use operator + to gain the same effect. For basic data-types, both operators are available. For class type, not both operators would be available, and you might ask the class' to implement required operator.

In my opinion, it is logical to ask operator + be defined by class. The reason is simple - doing T+T is more appropriate for most UDTs (User Defined Type), than having *= operator . Ask yourself: What does it mean if some class String or Date implements, or is asked, to implement following operator:

voidoperator *= (int); // void return type is for simplicity only.

At this point, you now clearly understand that template parameter type T may be inferred from T&, T* or T[].Therefore, it is also possible and very reasonable to add const attribute to the parameter which is arriving to function template, and that parameter would not be changed by function template. Take it easy, it is as simple as this:

Observe that I modified the template parameter TYPE to TYPE&, and also added const to it. Few or most of the readers would have realized the importance of this change. For those who didn't:

The TYPE type may be large in size, and would demand more space on stack (call-stack). It includes double which requires 8 bytes*, some structure or a class, which would demand more bytes to be kept on stack. It essentially means - a new object of given type would be created, copy constructor called, and be put into call stack, followed by destructor call at then end of function.Addition of reference (&) avoids all this - reference of same object is passed.

Function would not change the argument passed, and therefore addition of const to it. It ensures, to the caller of function, that this function (here PrintTwice), is not going to change the parameter's value. It also ensures a compiler error if, by mistake, the function itself tries to modify content of (constant) argument.

* On 32-bit platform, function arguments would require 4-bytes minimum, and in multiple of 4-bytes. This means a char or short would require 4 bytes in call-stack. An 11-byte object, for example would require 12-bytes in stack.Similarly, for 64-bit platform, 8-bytes would be needed. An 11-byte object would require 16-bytes. Argument of type double would need 8-bytes.All pointers/references takes 4-bytes/8-bytes respectively on 32-bit/64-bit platform, and therefore passing double or double& would mean the same for 64-bit platform.

Note that it is not possible to have reference and const added to return type, unless we intend to return reference (or pointer) of original object that was passed to the function template. The following code exemplifies it:

Note that this is just for illustration, and you would rarely see or write such code. You may, however see such code and may need to write, if the returned object is reference of some UDT. In that case member access operator dot (.) or arrow (->) would follow the function call. Anyway, this function template returns the reference of object which wins the greater-than race. This, definitely, requires operator > be defined by type T.

You should have noticed, I have not added const to any of two parameters passed. This is required; since function returns non-const reference of type T. Had it been like:

T& GetMax(const T& t1, const T& t2)

At the return statements, compiler would complain that t1 or t2 cannot be converted to non-const. If we add const to return type also ( const T& GetMax(...) ), following line at call site would fail to compile:

GetMax(x,y) = 0;

Since const object cannot be modified! You can definitely do forceful const/non-const typecasting, either in function or at call site. But that's a different aspect, a bad design and a non-recommended approach.

Till now I have covered only one type as template type parameters. With templates, you may have more than one template-type parameters. It goes like:

template<class T1, class T2, ... >

Where T1 and T2 are type-names to the function template. You may use any other specific name, rather than T1, T2. Note that the usage of '...' above does not mean that this template specification can take any number of arguments. It is just illustration that template may have any number of arguments. (As with C++11 standard, templates would allow variable number of arguments - but that thing is out of topic, for now.)

Where each call demands separate template instantiation for the first and second types being passed (or say inferred). Therefore, following three function template instances would be populated by compiler:

Realize that second and third instantiations are not same, as T1 and T2 would infer different data-types (int, double and double,int). Compiler will not perform any automatic conversion, as it might do for normal function call - A normal function taking int, for example, may be passed short, or vice-versa. But with templates, if you pass short - it is absolutely short, not (upgraded to) int. So, if you pass (short, int), (short, short), (long, int) - this would result in three different instantiations for PrintNumbers!

In similar fashion, function templates may have 3 or more type parameters, and each of them would map to the argument types specified in function call. As an example, the following function template is legal:

Where T1 specifies the type of array that would be passed by caller. If array (or pointer) is not passed, compiler will render appropriate error. The type T2 is used as return type as well as second argument, which is passed by value. Type T3 is passed as reference (a non-const reference). This function template example given above is just haphazardly chosen, but is a valid function template specification.

By now, I have stepped-up and elaborated multiple template parameters. But for a reason, I am stepping-down to one parameter function. There is a reason for this, and you will understand it in no time.

Assume that there is a function (non templated), which takes an int argument:

void Show(int nData);

And you call it as:

Show( 120 ); // 1
Show( 'X' ); // 2
Show( 55.64 ); // 3

Call 1 is perfectly valid since function takes int argument, and we are passing 120.

Call 2 is valid call since we are passing char, which will be promoted by compiler to int.

Call 3 would demand demotion of value - compiler has to convert double to int, and hence 55 would be passed instead of 55.64. Yes, this will trigger appropriate compiler warning.

One solution is to modify the function such that it takes double, where all three types can be passed. But that wouldn't support all types and may not fit in, or convertible to, double. Therefore, you may write set of overloaded functions, taking appropriate types. Armed with knowledge, now, you would appreciate the importance of templates, and would ask to write it a function template instead:

template<class Type>
void Show(Type tData) {}

Of course, assuming all existing overloads of Show were doing the same thing.

Alright, you know this drill. So, what's new in this which caused me to step-down?

Well, what if you wanted to pass int to function template Show, but wish the compiler instantiates as if double was passed?

// This will produce (instantiate) 'Show(int)'
Show ( 1234 );
// But you want it to produce 'Show(double)'

May seem illogical to demand this thing, as of now. But there is valid reason to demand such instantiation, which you will understand and appreciate soon!

Anyway, first see how to demand such absurd thing:

Show<double> ( 1234 );

Which instantiates the following template function (as you know):

void Show(double);

With this special syntax (Show<>()), you are demanding compiler to instantiate Show function for the type being explicitly passed, and asking the compiler not to deduce type by function argument.

Important! There is a difference between function template and template function.

A function template is body of a function that is bracketed around template keyword, which is not an actual function, and will not be fully compiled by compiler, and is not accountable by the linker. At least one call, for particular data-type(s) is needed to instantiate it, and be put into accountability of compiler and linker. Therefore, the instance of function template Show is instantiated as Show(int) or Show(double).

A template function? Simply put, an "instance of a function template", which is produced when you call it, or cause it to get instantiated for particular data type. The instance of function-template is actually a valid function.

An instance of a function template (aka template-function) is not a normal function, under the umbrella of name-decoration system of compiler and linker. That means, an instance of function-template:

template<class T>
void Show(T data)
{ }

for template argument double, it is not:

void Show(double data){}

but actually:

void Show<double>(double x){}

For long, I did not uncover this, only for simplicity, and now you know it! Use your compiler/debugger to find out the actual instantiation of a function template, and see the full prototype of a function in call-stack or generated code.

And what if you just needed only one instance - both arguments taking double? Yes, you are willing to pass ints and let them be promoted doubles. Coupled with the understanding you just gained, you would call this function-template as:

It would cause a compiler error, mentioning there is an ambiguity with template-type T. You are asking the compiler to deduce one type, from two types! One solution is to change max template so that it takes two template parameters - but you aren't author of that function template.

There you use explicit argument specification:

max<double>(120, 14.55); // Instantiates max<double>(double,double);

Undoubtedly notice and understand that I have passed explicit specification only for first template parameter, the second type is deduced from second argument of function call.

When function-template takes template-type, but not from its function arguments.

Which takes two ints, and sums them up. Though, summing them in int itself is appropriate, this function template gives opportunity to calculate the sum (using operator+) in any type as required by caller. For example, the get the result in double, you would call it as:

double nSum;
nSum = SumOfNumbers<double>(120,200);

The last two are just simplified examples for completeness, just to give you the hint where Explicit Template Argument Specification would fit in. There are more concrete scenarios where this explicitness would be needed, and would be covered in next part.

For readers, who do know about default template type specification in template' arena - this is not about default template-type arguments. Default template-types, is anyway, not allowed with function-templates. For readers, who do not know about it, do not worry - this paragraph is not about default template type specification.

As you know, a C++ function may have default arguments. The default-ness may only go from right to left, meaning, if nth argument is required to be default, (n+1)th must also be default, and so on till last argument of function.

This function template would print, as you can guess, all numbers except which are filtered out by third argument: filter. The last, optional function argument, is defaulted to default-value of type T, which, for all basic type would mean zero. Therefore, when you call it as:

int Array[10] = {1,2,0,3,4,2,5,6,0,7};
PrintNumbers(Array, 10);

It would be instantiated as:

void PrintNumbers(intarray[], int array_size, int filter = int())
{}

The filter argument would be rendered as: int filter = 0.

As obvious, when you call it as:

PrintNumbers(Array, 10, 2);

The third argument gets value 2, and not the default value 0.

It should be clearly understood that:

Type T must have default constructor available. And of course, all operators as may be required by function body, for type T.

The default argument must be deducible from the other non-default types the template takes. In PrintNumbers example, type of array would facilitate deduction for filter.If not, you must use explicit template argument specification to specify type of default argument.

For sure, the default argument may not necessarily be default value for type T (pardon the pun). It means, the default-argument may not always need to depend on default-constructor of type T:

Here, the default function argument doesn't use default-value for type T. Instead, it uses value 60. This, for sure, requires the type T to have copy-constructor which accepts an int (for 60).

Finally, here comes an end to 'Function Templates' for this part of article. I assume you enjoyed reading and grasping these basics of function templates. Next part would cover more intriguing aspects of Template programming.

More often, you would design and use class templates, than function templates. In general, you use a class template to define an abstract type whose behavior is generic and is reusable, adaptable. While some text would start by giving example about data-structures like linked-lists, stacks, queues and similar containers. I would start with very basic examples, that are easy to understand.

Let's take a simple class, which sets, gets and prints the value stored:

One constructor which initializes Data to 0, Set and Get methods, and a method to print current value. Usage is also quite simple:

Item item1;
item1.SetData(120);
item1.PrintData(); // Shows 120

Nothing new for you, for sure! But when you need similar abstraction for other data-type, you need to duplicate code of entire class (or at least the required methods). It incurs code maintenance issues, increases code size at source code as well as at binary level.

Yes, I can sense your intelligence that I am going to mention C++ templates! The templated version of the same class in form of class template is as below:

The class template declaration starts with same syntax as function templates:

template<class T>class Item

Note that the keyword class is used two times - firstly to specify template type specification (T), and secondly to specify that this is a C++ class declaration.

To completely turn Item into a class template, I replaced all instances of int with T. I also used T() syntax to call default constructor of T, instead of hard-coded 0 (zero), in the constructor's initializer' list. If you've read function templates section completely, you know the reason!

The code snippet shown above causes class template Item to instantiate as Item<int>. When you create another object with different type using Item class template as:

Item<float> item2;
float n = item2.GetData();

It would cause Item<float> to get instantiated. It is important to know that there is absolutely no relation between two instantiations of class template - Item<int> and Item<float>. For the compiler and linker, these two are different entities - or say, different classes.

First instantiation with type int produces following methods:

Item<int>::Item() constructor

SetData and PrintData methods for type int

Similarly, second instantiation with type float would produce:

Item<float>::Item() constructor

GetData method for float type

As you know Item<int> and Item<float> are two different classes/types; and therefore, following code will not work:

item1 = item2; // ERROR : Item<float> to Item<int>

Since both types are different, the compiler will not call possible default assignment operator. Had item1 and item2 were of same types (say both of Item<int>), the compiler would happily call assignment operator. Though, for the compiler, conversion between int and float is possible, it is not possible for different UDT conversions, even if underlying data members are same - this is simple C++ rule.

At this point, clearly understand that only following set of methods would get instantiated:

Item<int>::Item() - constructor

void Item<int>::SetData(int) method

void Item<int>::PrintData() const method

Item<float>::Item() - constructor

float Item<float>::GetData() const method

The following methods will not get second phase compilation:

int Item<int>::GetData() const

void Item<float>::SetData(float)

void Item<float>::PrintData() const

Now, what is a second phase compilation? Well, as I already elaborated that template-code would be compiled for basic syntax checks, irrespective of it being called/instantiated or not. This is known as first-phase compilation.

When you actually call, or somehow trigger it to be called, the function/method for the particular type(s) - then only it gets special treatment of second-phase compilation. Only through the second phase compilation, the code actually gets fully-compiled, against the type for which it is being instantiated.

Though, I could have elaborated this earlier, but this place is appropriate. How do you find out if function is getting first-phase and/or second-phase compilation?

Let's do something weird:

T GetData() const
{
for())return Data;
}

There is an extra parenthesis at the end of for - which is incorrect. When you compile it, you would get host of errors, irrespective of it being called or not. I have checked it using Visual C++ and GCC compilers, and both complain. This validates first-phase compilation.

Let's slightly change this to:

T GetData() const
{
T temp = Data[0];// Index access ?return Data;
}

Now compile it without calling GetData method for any type - and there won't be any quench from the compiler. This means, at this point, this function doesn't get phase-two compilation treatment!

As soon as you call:

Item<double> item3;
item2.GetData();

you would get error from compiler that Data is not an array or pointer, which could have operartor [] attached to it. It proves that only selected functions would get special privilege of phase-two compilation. And this phase-two compilation would happen separately for all unique types you instantiate class/function template for.

One interesting thing, you can do is:

T GetData() const
{
return Data % 10;
}

Which would get successfully compiled for Item<int>, but would fail for Item<float>:

Our first class-template Item had only one template type. Now let's construct a class that would have two template-type arguments. Again, there could have been somewhat complex class template example, I would like to keep it simple.

At times, you do require some native structure to keep few data members. Crafting a unique struct for the same appears somewhat needless and unnecessary-work. You would soon come out of names for different structures having few members in it. Also, it increases code length. Whatever your perspective may be for this, I am using it as an example, and deriving a class template having two members in it.

STL programmers would find this as equivalent to std::pair class template.

Assume you have a structure Point,

struct Point
{
int x;
int y;
};

which is having two data-members. Further, you may also have another structure Money:

struct Money
{
int Dollars;
int Cents;
};

Both of these structures have almost similar data-members in it. Instead of re-writing different structures, wouldn't it be better to have it at one place, which would also facilitate:

Constructor having one or two arguments of given types, and a copy-constructor.

Methods to compare two objects of same type.

Swapping between two types

And more.

You might say you can use inheritance model, where you'd define all required methods and let derive class customize it. Does it fit in? What about the data-types you chosen? It might be int, string, or float, some-class as types. In short, inheritance will only complicate the design, and will not allow plug-in feature facilitated by C++ templates.

There we use class templates! Just define a class template for two types, having all required methods. Let's start!

template<class Type1, classType2>
struct Pair
{
// In public area, since we want the client to use them directly.Type1 first;
Type2 second;
};

Now, we can use Pair class template to derive any type having two members. An example:

first would be of int type, and second would be of double type. Clearly understand that first and second are data-members, and not functions, and therefore there is no runtime penalty of assumed function call.

Note: In this part of article, all definitions are within the class declaration body only. In next part, I would explain how to implement methods in separate implementation file, and issues related with that. Therefore, all method definitions shown should be assumed within class ClassName{...}; only.

The following given default constructor would initialize both members to their default values, as per data type of Type1 and Type2:

Pair() : first(Type1()), second(Type2())
{}

Following is a parameterized constructor taking Type1 and Type2 to initialize values of first and second:

Pair(const Type1& t1, const Type2& t2) :
first(t1), second(t2)
{}

Following is a copy-constructor which would copy one Pair object from another Pair object, of exactly same type:

Please note that it is very much required to specify template type arguments of Pair<>, for the argument of this copy-constructor. The following specification wouldn't make sense, since Pair is not a non-template type:

Pair(constPair& OtherPair) // ERROR: Pair requires template-types

And here is an example using parametrized constructor and copy-constructor:

Pair<int,int> point1(12,40);
Pair<int,int> point2(point1);

It is important to note that if you change any of the template type parameters of either of the objects, point2 or point1,you wouldn't be able to copy-construct it using point1 object. Following would be an error:

Though, there is a possible conversion between float to int, but there is no possible conversion between Pair<int,float> to Pair<int,int>. The copy constructor cannot take other type as copyable object. There is a solution to this, but I would discuss it in next part.

In similar fashion, you can implement comparison operators to compare two objects of same Pair type. Following is an implementation of equal-to operator:

Note that I used const attribute, for argument and for the method itself. Please fully understand the first line of above' method definition!

Just like copy-constructor call, you must pass exactly the same type to this comparison operator - compiler will not attempt to convert different Pair types. An example:

if (point1 == point2) // Both objects must be of same type.
...

For a solid understanding for the concepts covered till here, please implement following methods by on your own:

All remaining 5 relational operators

Assignment operator

Swap method

Modify both constructors (except copy-constructor), and combine them into one so that they take both parameters as default. This means, implement only one constructor that can take 0,1 or 2 arguments.

Pair class is an example for two types, and it can be used instead of defining multiple structures having just two data-members. The drawback is just with remembering what first and second would mean (X or Y?). But when you well-define a template instantiation, you would always know and use first and second members appropriately.

Ignoring this one disadvantage, you would achieve all the features in the instantiated type: constructors, copy-constructor, comparison operators, swap method etc. And, you'd get all this without re-writing the required code for various two-member structures you would need. Furthermore, as you know, only the set of required methods would get compiled and linked. A bug fix in class template would automatically be reflected to all instantiations. Yes, a slight modification to class template may also raise bunch of errors, of other types, if the modification fails to comply with existing usage.

Likewise, you can have a class template tuple which allows three (or more) data-members. Please try to implement class tuple with three members (first, second, third) by yourself:

Alright, we have seen that class templates, just like function templates, can take multiple type arguments. But class templates also allow few non-type template arguments. In this part, I will elaborate only one non-type: integer.

Yes, a class template may take a integer as template argument. First a sample:

template<class T, int SIZE>
class Array{};

In this class template declaration, int SIZE is a non-type argument, which is an integer.

Only integral data-types can be non-type integer argument, it includes int, char, long, long long, unsigned variants and enums. Types such as float and double are not allowed.

When being instantiated, only compile time constant integer can be passed. This means 100, 100+99, 1<<3 etc are allowed, since they are compiled time constant expressions. Arguments, that involve function call, like abs(-120), are not allowed.As a template argument, floats/doubles etc may be allowed, if they can be converted to integer.

Fine. We can instantiate class template Array as:

Array<int, 10> my_array;

So what? What's the purpose of SIZE argument?

Well, within the class template you can use this non-type integer argument, wherever you could have used an integer. It includes:

Note that first overload (which is declared const) is get/read method, and has a check to see if index is valid or not, otherwise returns default value for type T.

The second overload returns the reference of an element, which can be modified by caller. There is no index validity check, since it has to return a reference, and therefore local-object (T()) cannot be returned. You may, however, check the index argument, return default value, use assertion and/or throw an exception.

Let's define another method, which would logically sum all the elements of Array:

As you can interpret, it requires operator += to be available for target type T. Also note that return type is T itself, which is appropriate. So, when instantiate Array with some string class, it will call += on each iteration and would return the combined string. If target type doesn't have this += operator defined, and you call this method, there would be an error. In that case, you either - don't call it; or implement the required operator overload in the target class.

While it is a vague statement to understand, and invites some ambiguities, I would attempt my best to remove the fogginess.

First, recollect the difference between template-function and a function-template. If the neurons have helped to transfer the correct information to the cache of your brain-box, you now callback that template-function is an instance of function-template. If search-subsystem of your brain is not responding, please reload the information again!

An instance of class template is template class. Therefore, for following class template:

template<class T1, class T2>
class Pair{};

The instantiation of this template is a template-class:

Pair<int,int> IntPair;

Clearly understand that IntPair is not a template-class, is not instantiation for class template. It is an object of a particular instantiation/class-template. The template-class/instantiation is Pair<int,int>, which produces another class type (compiler, our friend does this, you know!). Essentially this is what template-class would be produced by compiler for this case:

classPair<int,int>{};

There is more precise definition for a template-class, select this single line of code for easy understanding. Detailed explication would come in next installment of this series.

Now, let's come to the point. What if you pass a template-class to some class-template? I mean, what does it mean by following statement?

Pair<int, Pair<int,int> > PairOfPair;

Is it valid - if so, what does it mean? Firstly, it is perfectly valid. Secondly, it instantiates two template classes:

Pair<int,int> - A

Pair<int, Pair<int,int> > -- B

Both A and B types would be instantiated by compiler, and if there is any error, arising due to any type of these two template classes, compiler would report. To simplify this complex instantiation, you may do:

Note that second member in last two lines is of type Pair<int,int>, and therefore it has same set of members to be accessed further. That's the reason first and second members can be used, in cascaded manner.

Now you (hopefully) understand that class template (Pair) is taking template-class (Pair<int,int>)as argument and inducing the final instantiation!

An interesting instantiation, in this discussion, would be of Array with Pair! You know that Pair takes two template type arguments, and Array takes one type argument, and a size (integer) argument.

Array< Pair<int, double>, 40> ArrayOfPair;

Here int and double are type-arguments for Pair. Hence, the first template-type of Array (marked bold) is Pair<int,double>. The second argument is constant 40. Can you answer this: Would the constructor of Pair<int,double> be called? When it will be called? Before you answer that, I just reverse the instantiation as:

Pair<int, Array<double, 50>> PairOfArray;

Wohoo! What does it mean? Well, it means: PairOfArray is an instantiation of Pair, which is taking first type as int (for first member), and second type (second) is an Array. Where Array (the second type of Pair) is 50 elements of type double!

Don't kill me for this! Slowly and clearly understand these basic concepts of templates. Once you get the crystal-clear understanding, you would love templates!

Here again, I used a template-class (Array<double,50>) as an argument to an instance of other type (Pair<int,...>).

Okay, but what right-shift operator (>>) is doing above? Well, that's not an operator, but just ending of Array's type specification, followed by ending of Pair type specification. Some old compilers required us to put a space in between two greater-than symbols, so to avoid error or confusion.

Pair<int, Array<double, 50> > PairOfArray;

At present, almost all modern C++ compilers are smart enough to understand that this is used to end template type specification, and therefore you need not to worry. Therefore, you may freely use two or more > symbols to end template specification(s).

Kindly note that passing a template class (instantiation) is nothing very specific in C++ terms - it is just a type that a class template would take.

Finally, Here I put usage examples both objects. First the constructors.

Array< Pair<int, double>, 40> ArrayOfPair;

This will cause the constructor of Pair to be called 40 times, since there is declaration of constant-size array in Array class template:

T TheArray[SIZE];

Which would mean:

Pair<int,double> TheArray[40];

And hence the required number of calls to constructor of Pair.

For the following object construction:

Pair<int, Array<double, 50>> PairOfArray;

The constructor of Pair would initialize first argument with 0 (using int() notation), and would call constructor of Array with Array() notation, as shown below:

Pair() : first(int()), second(Array())
{}

Since the default constructor of Array class template is provided by compiler, it would be called. If you don't understand the stuff written here, please sharpen your C++ skills.

Assigning one element of ArrayOfPair:

ArrayOfPair[0] = Pair<int,double>(40, 3.14159);

Here, you are calling non-const version of Array::operator[], which would return the reference of first element of Array (from TheArray). The element, as you know, is of type Pair<int,double>. The expression on right side of assignment operator is just calling the constructor for Pair<int,double> and passing required two arguments. The assignment is done!

First let me eliminate any ambiguity with 'Default Argument' phrase. The same phrase was used in Function Template section. In that sub-section, the default-argument referred to arguments of function parameters itself, not the type-arguments of function template. Function templates, anyway, do not support default arguments for template-arguments. As a side note, please know that methods of a class template can take default arguments, as any ordinary function/method would take.

Class templates, on other hand, do support default-argument for the type/non-type arguments for the template parameters. Throwing you an example:

I have just modified around SIZE in first line for class template Array. The second template parameter, an integer constant specification, is now set to 100. It means, when you use it in following manner:

Array<int> IntArray;

It would essentially mean:

Array<int, 100> IntArray;

Which would be automatically placed by compiler during the instantiation of this class template. Of course, you can specify custom array size by explicitly passing the second template argument:

Array<int, 200> IntArray;

Do remember that when you explicitly pass the default argument's parameter, with the same argument specified in class template declaration, it would instantiate it only once. By this, I mean, the following two objects created would instantiate only one class: Array<int,100>

Array<int> Array1;
Array<int,100> Array2;

Of course, if you change the default' template parameter in class template definition, with value other than 100, it would cause two template instantiations, since they would be different types.

For sure, using _size symbol instead of hard-coded constant value mean the same. But using a symbol would ease the default' specification. Irrespective of how you specify the default template parameter for integer (which is a non-type template argument), it must be a compile time constant expression.

You would generally not use default specification for non-type integer parameter, unless you are utilizing templates for advanced stuff, like meta-programming, static-asserts, SFINAE etc, which definitely demands a separate part. More often you would see and implement default parameters for class templates, which are data-types. An example:

template<class T = int>
class Array100
{
T TheArray[100];
};

It defines an array of type T of size 100. Here, the type argument is defaulted to int. That means, if you don't specify the type while instantiating Array100, it would map to int. Following is an example on how to use it:

Array100<float> FloatArray;
Array100<> IntArray;

In the first instantiation, I passed float as template type, and in second call I kept it default (to int), by using <> notation. While there are more uses of this notation in template programming, which I would cover up in later parts, it is very much required for this case also. If you try to use the class template as:

Array100 IntArray;

It would result in compiler errors, saying Array100 requires template parameters. Therefore, you must use empty-set of angle-brackets (<>) to instantiate a class template, if all template arguments are default, and you wish to use defaults.

Important thing to remember is that a non-template class of name Array100 will not be allowed also. Definition of a non-template class like as given below, along with template class (above or below each other), will upset the compiler:

Finally, both type and the size arguments are marked default with int and 100 respectively. Clearly understand that first int is for default specification of T, and second int is for non-template constant specification. For simplicity and better readability, you should keep them in different lines:

template<class T = int,
intSIZE=100>
class Array{};

Now, use use your intelligence to parse the meaning of following instantiations:

As a final note, do remember that following two object creations would instantiate only one class template, since essentially they are exactly the same:

Array<> IntArray1;
Array<int> IntArray2
Array<int, 100> IntArray3;

Defaulting a template type on another type

It is also possible to default a type/non-type parameter on a previously arrived template parameter. For instance, we can modify the Pair class so that second type would be same as first type, if second type is not explicitly specified.

Though, this one isn't for absolute beginners, but since I have covered both function templates and class templates - the elaboration of this concept is logical for this first part of this series itself.

The class IntArray is simple, non-template class, having an integer array of 10 elements. But the method Copy is a designed as a function template (method template?). It takes one template type parameter, which would be deduced by compiler automatically. Here is how we can use it:

As you can guess, IntArray::Copy would be instantiated with type float, since we are passing float-array to it. To avoid confusion and understand it better, just think of int_array.Copy as Copy only, and IntArray::Copy<float>(..) as Copy<float>(..) only. The method template of a class is nothing but an ordinary function template embedded in a class.

Do notice that I used 10 as array size everywhere. Interestingly, we can also modify the class as:

Which makes the class IntArray and the method Copy, better candidates to be in the realm of template programming!

As you would have intelligently guessed, Copy method is nothing but an array-conversion routine, which converts from int to any type, wherever conversion from int to given type is possible. This is one of the valid case where class method can be written as function templates, taking template arguments by themselves. Please modify this class template so that it can work for any type of array, not just int.

For sure, 'explicit template argument specification' with method template is also possible. Consider another example:

On one hand it provides good flexibility, since without writing extra code, Convert can convert itself (the specific instantiation) to any data-type - whenever conversion is possible at compilation level. If conversion is not possible, like from double to string-type, it would raise an error.

But on the other hand, it also invites trouble by possibility of inadvertently inserting bugs. You may not want to have conversion operator called, and it is called (compiler code generated) without you knowing about it.

You have just seen slight glimpse of power and flexibility provided by templates. Next part will cover more of advanced and intriguing concepts. My humble and aspiring request to all readers is to play more and more with templates. Try to gain firm understanding on one aspect first (like function template only), rather than just hastily jumping to other concept. Initially do it with your test projects/code-base, and not with any existing/working/production code.

Following is a summary of what we have covered:

To avoid unnecessary code duplication and code maintenance issues, specially when code is exactly same, we can use templates. Templates are far better approach than using C/C++ macros or functions/classes running on top of void-pointers.

Templates are not only type-safe, but also reduces unnecessary code-bloat which would not be referred (not generated by compiler).

Function templates are used to put a code that is not a part of class, and is same/almost-same for different data-types. At most of the places, compiler would automatically determine the type. Otherwise you have to specify the type, or you may also specify explicit type yourself.

thanks a lot ajay for the material and the effort you took to respond, you are really great and responsible, i had just few problems in implementing the copy constructor and assignment operator, related to const, now it got resolved, actually i couldnt recall what was the issue but the error is not coming again ( weird but smtime this happens )

You've obviously put a lot of work into your articles, and I plan on going through them carefully to see if there is something about templates that I don't know, and should. With that in mind, please don't take the following as a criticism of you or your work.

You see I've used templates in the past and always end up ripping them out due to compiler differences, problems debugging (the debuggers often have no clue on how to deal with a watched template variable) and just general code readability. I've written many cross platform applications and templates always are a stumbling block. My C++ looks very much like C with classes.

To show you what I'm talking about.

Your first example shows how the overloaded ostream can reduce code. Specifically

This is the sort of example that I've always had problems with, because it always seems contrived. You don't usually want to format integers and floats the same way. I know that the ostream library has these functions overloaded, I'm not saving any space, and I also know that the printf method is more flexible.
For instance, what if you wanted to do the same example but formatted specifically for integers or floats. Or what if this function buried deep in the system starts to be called with a TYPE that cannot be multiplied by 2, like a string. As an extra insult to readability I really hate the ugly endl; It reminds me of cobal or pascal. I also hate trying to remember all the weird little special things that templates need or expect like endl or <<

As I said before, when I write C++, it looks more like C with classes. This is because C provides all the overloading functionally that I really need. Take for example qsort. A function that has been in the standard since the early 90's. It can sort anything. It does this by accepting a pointer to a function that does the compare. The compare can be as complex or simple as you want. I've even done things like reindex a file by sorting an array of integers that were offsets into the records. The compare read the records in and compared on the field appropriate. After the array was sorted, it was a simple matter of reading the file offset by the index and writing out a new one based on the array. I have no idea how I would do that by overloading templates. The best use of C++ classes is to help organize functions that go with structures. I also like exceptions. However templates always seem more trouble then they are worth, and always cause problems down the road.

As proof of this, different versions of Boost, will only work for certain compilers. There is no way I'm debugging by tracing through boost headers!

I do agree with your point with string-formatting, even I do you printf-family of functions instead of ostream classes. The examples given are only for illustration, and not of personal choice, reducing source code size and so on. At this "for-beginners" stage, I do not find anything simpler that displaying-on-screen, and hence the set of printfs and couts.

But I don't agree with your qsort justification - I can sort anything, for sure. But that kind of code is unreadable, bug prone, and leaves no ground for compiler optimization. There are no type-traits around qsort, it cannot work with non-random collection, cannot utilize r-value references, will not be able to call compare-function automatically for some type T. It won't also be able to utilize parallelism of sorting.

I don't understand why you are advocating old C-style functional approach, when <string.h> itself is demanded to be binned as deprecated? C++ guys around the world are trying hard to make classes under std namespace to be programmer and compiler friendly. I doesn't matter what you could have done with C language, but you are for sure missing nifty features of C++, even if you dont/cant use templates.

I don't see how qsort is unreadable. You pass in what you are sorting and the size, and a function to compare. The function to compare returns -1,0 or 1 depending on what is passed in. I suppose if you don't like casting void * to array elements then it might seem messy, but to me that's loads better then the great unknown of templates that you hope do what you want. At least when you are doing the cast, you have control.

As for compiler optimization, wikipedia says that , on average, makes O(n log n) comparisons to sort n items. In the worst case, it makes O(n^2) comparisons. I've been happy with it It's a library function, so compiler optimizations have already been done.

There are no type-traits around qsort because they aren't needed (or in my view desired).

It can work with a non-random collection (why wouldn't it, it's just an instance of the set of possiblities in the array to be sorted).

r-value references have only been in the standard for a year, so good luck using old compilers with that. (You are making me work here. I don't even know what r-value references do).

Will not be able to call compare-function automatically? That's it's beauty! When compilers start doing things automagically that's when weird bugs creep in that are impossible to solve. I would much rather tell my code what I want to happen then hope that the current compiler that I'm using is going to give me the same results as the other 6 that I'm using.

qsort also (according to wikipedia), can be parallelized. But that's beyond anything I've ever needed to do.

The reason I advocate the "old C-style" functional approach is that it is controllable, is used throughout the world, is stable, and is portable. There is a reason that the Linux kernel is written in C and not C++. It is far from depreciated.

On the other hand, I don't throw all C++ features out. I use exceptions, and classes, enums, and so on. But I strictly limit what I will allow the compiler to do for me. I'm a control freak because I program defensively. I program to avoid the problem of 6 years from now, I'll have some template that is a mess of angle brackets that I won't be able to figure out.

C++'s reference is a stupid idea. You cannot tell from the calling function "bar" which function modifies a. Is it foo or food? At least with pointers, the calling function has to send the address of a variable. If a reference had some indication that the passed variable was a reference then I'd be all for it. But Stroustrup didn't think it was important. I guess he didn't have to maintain old code.

I think templates fall into the same area. Things are hidden from the programmer to "protect" the programmer, and to make the programmers life easier. Except that they don't.

Sorry, didn't mean to sound so aggressive. As I said in my original message, I have a lot of respect for you for writing the articles in the first place. I was just debating the points, no offence meant.

Also, I don't say that C is better, I say that C++ without templates is better

Size of array as template parameter would work, for sure. But this isn't my production code, this is tutorial, and has to have some (learning) pace. You see all concepts are very basic in this article.

As for my English, I agree with the clumsiness, and I need to improve it. But what sentence you mean has probably the oppisite meaning?

Tries to simplify templates then immediately makes it hard by throwing in too much C++ variations that just muddy the water. Then leaves you wondering where you use class or typename
i.e. "there are instances where you can only use the newer keyword - typename" and the answer is ?

It is expected from reader to know what copy constructor, const parameters, conversion operators are, so I don't agree it is too much of C++. This article isn't about C++, but about templates in C++, which is often neglected.

There are instances, where it is required to give some idea about some concept. If reader has inquisitiveness, he/she can definitely locate information for the same. Why mentioning something is worse than not mentioning it at all?

BTW, typename is very-much required when type is dependent on other type. For eg:

It is expected from reader to know what copy constructor, const parameters,
conversion operators are, so I don't agree it is too much of C++.

Actually meant mentioning these complicated the article, the user should know these - Its the old saying 'Less is sometimes more'!

Ajay Vijayvargiya wrote:

It is however, recommended to always use typename instead of class

Thanks for clarifying - but why use class at all in the article?

Generally - Templates are a great idea but badly implemented in terms of usability, even more so with STL.
STL has all the classic reasons why people don't like C++. For example just compare ease of use of the MFC container libraries compared to using STL, yes STL is more flexible but at what price of usability!

Sometimes it's better to have an easier to use libary that obeys the 80:20 rule.
i.e. 80% of peple will use only 20% of the features - suspect in STL its probably nearer 95:5!

Good article just needs an editors touch - even the best writers need an editor

Once your mind is stretched with a new idea, it will never regain its original dimension.

Few months/years ago, even I liked MFC and other non-STL stuff, and appreciated the ease of programming. But STL/templates do have much more than those "simple" techniques. MFC containers, few of them, as not typesafe, and you are allowed to pass any type to them. No compiler type check is performed. Few container classes, like CArray, do have type-safety - but they fail at runtime to detect bug. Yes, there are ASSERTs in MFC, but they are mostly around CWnd-stuff, and not around container classes.

STL do implicitly have compiler support for bug-detection, and reasonably good asserts at runtime. STL is very much flexible, MFC is not. STL is platform/compiler independent. I dont' detest MFC, as I do like MFC - but not for data and algos.

When they/you would need to use some algorithm, like sort or find_if, you'd definitely need to use STL container. And, there you'd selectively use STL, and not MFC! Or use some home-written, untested, bug-prone algo!

Yes - the standard C++ qsort does works for most of our humble requirements!
The wide range of STL looks great, but think it would have been nice if they had been written with the user in mind, not to mention the horrendous bugs (early days) and unreadable diagnostics (even today) it pumps out!

The words 'User friendly' is hard to apply to STL.

Unfortunately it's a problem with a lot of things where bad design often comes a standard - web technologies is a primary example of that!

Don't think anyone would think Javascript, HTML, Browsers etc are icons of 'brilliant' design, as a C++ user think you would agree with that! But they do a job, STL is the reverse, well designed technically but badly designed from the users perspective!

Worth looking at the classic book Effective STL by Scott Meyers especially Item 49 'Learn to decipher STL-related compiler diagnostics' - about sums up my view of why STL is not user friendly!

Oh, and if STL was user friendly you probably would not need to write an article about it

Your last statement is true (to some extent) but I would go much further. While C++ is a powerful and elegant language in many ways, most people aren't cut out to program for a living, let alone in a language whose own author once said you can (potentially) blow your leg off with it (an inexact quote but the sentiment is there). Don't get me wrong, I once met Stroustrup and he's as smart as you would think he is (and a very nice guy). Most organizations should avoid C++ however (sorry Bjarne) and if they are going to use it (or chose to use it at a time when no viable alternatives existed), then the use of templates should be kept to a minimum. Too many people are caught up in the allure of C++ but if they really understood the negative impact it has on cost and stability (in most organizations), they would avoid it if possible.

when you nest other types inside template class that do not depend on template parameters , compiler does not treat them as types at all, ie they are non dependent types. Because of potential specialization, the compiler does not and probably cannot know the nested class is a type unless the T of the hosting class is known in advance. Thus typename in front of the nested type required to tell compiler that it is indeed the nested type type.