Generics in C++
Starting with version 1.18, C++ has added support for templates, which are similar to generics in other languages.
As an example of a template function, SlicesIndex
takes a vector of any comparable type and an element of that type and returns the index of the first occurrence of v in s, or -1 if not present. The std::vector
and std::equal_to
are used to achieve this functionality.
#include <iostream>
#include <vector>
#include <algorithm>
template<typename S, typename E>
int SlicesIndex(const S& s, const E& v) {
auto it = std::find(s.begin(), s.end(), v);
if (it != s.end()) {
return std::distance(s.begin(), it);
}
return -1;
}
As an example of a template class, List
is a singly-linked list with values of any type.
template<typename T>
class List {
private:
struct element {
element* next;
T val;
element(const T& v) : next(nullptr), val(v) {}
};
element *head, *tail;
public:
List() : head(nullptr), tail(nullptr) {}
void Push(const T& v) {
element* new_elem = new element(v);
if (tail == nullptr) {
head = tail = new_elem;
} else {
tail->next = new_elem;
tail = new_elem;
}
}
std::vector<T> AllElements() const {
std::vector<T> elems;
for (element* e = head; e != nullptr; e = e->next) {
elems.push_back(e->val);
}
return elems;
}
~List() {
while (head) {
element* temp = head;
head = head->next;
delete temp;
}
}
};
Here’s how we can use these template functions and classes:
int main() {
std::vector<std::string> s = {"foo", "bar", "zoo"};
std::cout << "index of zoo: " << SlicesIndex(s, std::string("zoo")) << std::endl;
List<int> lst;
lst.Push(10);
lst.Push(13);
lst.Push(23);
std::cout << "list: ";
for (int val : lst.AllElements()) {
std::cout << val << " ";
}
std::cout << std::endl;
return 0;
}
When compiling and running this program, you should see:
$ g++ -std=c++17 generics.cpp -o generics
$ ./generics
index of zoo: 2
list: 10 13 23
In C++, templates are a compile-time feature, which means that the compiler generates specialized code for each type the template is used with. This can lead to better performance compared to runtime polymorphism, but it can also increase compile times and code size.