Templates

Classes can be templated, which means that you can write generic code and the compiler will generate a class with the types that your code uses. The parameters can be types, constant integer values, or variadic versions (zero or more parameters, as provided by the code using the class). For example:

    template <int N, typename T> class simple_array 
{
T data[N];
public:
const T* begin() const { return data; }
const T* end() const { return data + N; }
int size() const { return N; }

T& operator[](int idx)
{
if (idx < 0 || idx >= N)
throw range_error("Range 0 to " + to_string(N));
return data[idx];
}
};

Here is a very simple array class that defines the basic iterator functions and the indexing operator, so that you can call it like this:

    simple_array<4, int> four; 
four[0] = 10; four[1] = 20; four[2] = 30; four[3] = 40;
for(int i : four) cout << i << " "; // 10 20 30 40
cout << endl;
four[4] = -99; // throws a range_error exception

If you choose to define a function out of the class declaration, then you need to give the template and its parameters as part of the class name:

    template<int N, typename T> 
T& simple_array<N,T>::operator[](int idx)
{
if (idx < 0 || idx >= N)
throw range_error("Range 0 to " + to_string(N));
return data[idx];
}

You can also have default values for template parameters:

    template<int N, typename T=int> class simple_array 
{
// same as before
};

If you think you should have a specific implementation for a template parameter, then you can provide the code for that version as a specialization of the template:

    template<int N> class simple_array<N, char> 
{
char data[N];
public:
simple_array<N, char>(const char* str)
{
strncpy(data, str, N);
}
int size() const { return N; }
char& operator[](int idx)
{
if (idx < 0 || idx >= N)
throw range_error("Range 0 to " + to_string(N));
return data[idx];
}
operator const char*() const { return data; }
};

Note that, with a specialization, you do not get any code from the fully templated class; you have to implement all the methods you want to provide, and, as illustrated here, methods that are relevant to the specialization but not available on the fully templated class. This example is a partial specialization, meaning that it is specialized on just one parameter (T, the type of the data). This class will be used for declared variables of the type simple_array<n, char>, where n is an integer. You are free to have a fully specialized template, which, in this case, will be a specialization for a fixed size and a specified type:

    template<> class simple_array<256, char> 
{
char data[256];
public:
// etc
};

It is probably not useful in this case, but the idea is that there will be special code for variables that need 256 chars.