CPP as a second language

Using templates

Overview

Teaching: 10 min
Exercises: 5 min
Questions
  • What are templates?

  • What is generic programming?

  • What is the STL?

  • How do you use the STL?

Objectives
  • Use the STL vector template.

Templates allow for generic types. With templates it is possible to write a function or a class which can operator on any type (or class) of data. For example our Vector class only works with ints but using templates we could create it in such a way that it would work with any type, including types created by us or other programmers.

However, before we rush off and learn about creating templates to further generalize and extend our Vector class it turns out that there is already a class available in the standard template library which does something similar. The standard template library (or STL) has many different types of container classes, vector, queue, stack, list, set, map … which can be used to contain basic or user created types. Lets try out using the STL vector class as an example of how to use these containers.

$ nano stl_vector.cpp
#include <iostream>
#include <vector>

void displayVector(std::vector<int>& vec){
  for(int i=0;i<vec.size();++i){
    std::cout<<vec[i]<<" ";
  }
  std::cout<<"\n";
};

int main(){
  std::vector<int> a;
  a.push_back(0);
  a.push_back(1);
  a.push_back(2);
  displayVector(a);
}

stl_vector.cpp

From looking at the standard template library reference we can see that std::vector has a push_back member function, which allows us to add new items to the end of the vector. It has an operator[] which allows us to access items within the vector. Finally it has a size member function which lets us know how big the vector is.

$ g++ stl_vector.cpp -o stl_vector
$ ./stl_vector
0 1 2

The container std::vector is a template class. What this means is that when we have a line in our code like std::vector<int> and we compile the code, the compiler will create a vector class that works for int data types at compile time based on the template provided in the ‘vector’ header we included with #include <vector>. If we had multiple different lines with std::vector<some type> a new version would be created at compile time for each type. This means that compile times can get rather lengthy when templates are used heavily. However, putting this time and work into compile time can sometimes result in faster code at run time as different code paths are decided at compile time rather than run time, as would be the case using inheritance with virtual functions. Depending on your situation fast, write > compile > test iterations might be important to you, or your priority might be to trade compile time for faster running executables.

Iterators

It is common with the STL containers to support the ‘iterator’ method of looping over elements. While what we did above works just fine for std::vector, it will not work for containers which do not behave like arrays. For example it will not work for std::list, while the iterator method shown below will work for most STL containers (e.g. array, list, map, set, vector).

std::vector<int> a;
std::vector<int>::iterator it;
for(it=a.begin();it!=v.end();++it){
  std::cout<<*it<<"\n";
}

For more information about using iterators see this programming tutorial

Key Points