In my previous articles I talked about what templates in C++ are and it's types with examples. Here I'm going to show you a little power of templates, I'm going to model my own array which can take hold multiple types. First I'm going to model an array of int
then turn it into an array that can conform to multiple types, Let's get started:
#pragma once
#include <iostream>
template<int S>
class Array{
friend std::ostream &operator<<(std::ostream &os, const Array<S> &arr){ //OVERLOADED STREAM INSERTION OPERATOR
os << "[ ";
for(const auto &a: arr.data)
os << a << " ";
os << "]";
return os;
}
int data[S];
int size{S};
static const int limit{};
public:
Array() = default;
Array(int ini = 0){
for(auto &a: data)
a = ini;
}
int get_size() const{ //RETURNS THE SIZE OF THE ARRAY
return size;
}
void fill(int fil, int stop = limit){ //CHANGES ALL THE VALUE OF THE ARRAY UP TO A SPECIFIED POINT
for(int i{0}; i <= stop; ++i)
data[i] = fil;
}
void set(int index, int info){ //CHANGES THE VALUE OF THE ARRAY AT A PARTICULAR INDEX
data[index] = info;
}
int &operator[](int a){ //OVERLOADED SUBSCRIPT OPERATOR
return data[a];
}
};
Let's understand what's going on in the code, i created a template
which has an int
S as it's template parameter which is what we use to represent the fixed size of an array, then i go ahead and create a class Array
whose data members is:
- An array of
int
'data' whose size is dependent on the value thatS
takes during the creation of theArray
object- An
int
'size' which represents the size of the array and is initialized to the value ofS
- A
static const int
'limit' which i just use to give a particular function in the class more power, it's not really needed in the program
I have a constructor that initializes all the value in the array to whatever the user passed in, then a function that returns the size of the array, a fill
function which expects two int
values, the first being the value that will replace the ones already in the array and the second being a sort-of 'limiter' to the fill
function by allowing the user to set the range which the fill
function affects. I also have a set
function which replaces the value of the array at a specified index and then i have two overloaded operators:
Subscript operator
[]
which lets us access the value of the array at a specified index.Stream insertion operator
<<
which lets us output anArray
object easily.
Now we have a model of an Array of int
and I've ran some tests to show you -
Everything works fine, now we want to make this class able to model other data types without writing multiple classes for the different types, as usual we use templates to accomplish this:
#pragma once
#include <iostream>
template<typename T, int S>
class Array{
friend std::ostream &operator<<(std::ostream &os, const Array<T, S> &arr){ //OVERLOADED STREAM INSERTION OPERATOR
os << "[ ";
for(const auto &a: arr.data)
os << a << " ";
os << "]";
return os;
}
T data[S];
int size{S};
static const int limit{S};
public:
Array() = default;
Array(T ini = 0){
for(auto &a: data)
a = ini;
}
int get_size() const{ //RETURNS THE SIZE OF THE ARRAY
return size;
}
void fill(T fil, int stop = limit){ //CHANGES ALL THE VALUE OF THE ARRAY UP TO A SPECIFIED POINT
for(int i{0}; i <= stop; ++i)
data[i] = fil;
}
void set(int index, T info){ //CHANGES THE VALUE OF THE ARRAY AT A PARTICULAR INDEX
data[index] = info;
}
T &operator[](int a){ //OVERLOADED SUBSCRIPT OPERATOR
return data[a];
}
};
That's it, Let's walk through it. I've added another template parameter 'T' which represents the type that the array would represent, so we replace some places where int
used to be with T
since the type the array takes is dependent on what the user sets 'T' as, but we don't change int size
and int stop = limit
because they always has to be an integer obviously, we change the overloaded []
operator to return a reference to a T
object rather than an int
and the fill
function now expects a 'T' object rather than an int
because now the array doesn't have a definite type unlike before. Let's run some tests:
So that's about it, that's a simple way to model an array of multiple types using templates, it can be tweaked to do other things, other class functions can be added to make it do more and stuff, here's the test codes in case you want to copy into your IDE:
#include <Array.h>
#include <string>
using std::cout;
using std::cin;
using std::endl;
int main(){
Array<double, 4> arr{5.4};
cout << arr << endl;
arr.fill(6.1, 2); //REMEMBER COUNTING STARTS FROM 0
cout << arr << endl;
arr.set(0, 9.7);
cout << arr << endl;
arr[1] = 2.3;
cout << arr << "\n"<< endl;
Array<std::string, 4> str{"Hi"};
cout << str << endl;
str.fill("Bye", 1);
cout << str << endl;
str.set(2, "Bad");
cout << str << endl;
str[3] = "Human";
cout << str << endl;
return 0;
}
If you have any questions, you can message me on twitter or on discord (Padawan #4324)