In my experience with C++ programming, templates and generic programming have proven to be indispensable tools for creating flexible and efficient code. The introduction of templates revolutionised the way we write code by allowing functions and classes to operate with generic types. In this blog post, I will delve into function templates, class templates, and template specialisation, illustrating how they contribute to the power of generic programming in C++17.

Function Templates

Function templates enable us to write functions that can operate with any data type. This is particularly useful when the same logic applies to different types, and rewriting code for each type would be inefficient.

Example: A Generic Swap Function

template <typename T>
void swap(T& a, T& b) {
    T temp = a;
    a = b;
    b = temp;
}

In this example, the swap function can interchange the values of any two variables of the same type. The typename T indicates that T is a placeholder for any data type. This eliminates the need to overload the function for different types such as int, float, or std::string.

Class Templates

Class templates allow classes to operate with generic types in a similar fashion to function templates. They are particularly useful for data structures and container classes.

Example: A Simple Generic Pair Class

template <typename T1, typename T2>
class Pair {
public:
    T1 first;
    T2 second;

    Pair(const T1& a, const T2& b) : first(a), second(b) {}
};

The Pair class can hold two values of any types. This is beneficial when we need to create associations between different types without specifying them in advance.

Usage:

Pair<int, std::string> p(1, "one");
std::cout << p.first << ", " << p.second << std::endl;

Template Specialisation

Template specialisation allows us to define custom implementations for specific types while retaining the generic implementation for other types. There are two types of specialisation: full and partial.

Full Specialisation

Full specialisation involves providing a specific implementation for a particular type.

Example:

template <>
void swap<bool>(bool& a, bool& b) {
    // Special implementation for bool
    bool temp = a;
    a = b;
    b = temp;
}

Here, we have provided a specialised version of the swap function for bool types, although in this simple case, it behaves the same as the generic version.

Partial Specialisation

Partial specialisation is applicable to class templates and allows us to specialise a template based on certain template parameters.

Example: Specialising a Pair with the Same Types

template <typename T>
class Pair<T, T> {
public:
    T first;
    T second;

    Pair(const T& a, const T& b) : first(a), second(b) {}

    T sum() { return first + second; }
};

In this specialisation, the Pair class is customised for cases where both types are the same, adding a sum function that makes sense only when the types support the + operator.

Advantages of Generic Programming

Generic programming offers several significant benefits:

  1. Code Reusability: Templates allow us to write code once and reuse it for any data type, reducing duplication and potential errors.
  2. Type Safety: Unlike void pointers or macros, templates are type-safe, catching errors at compile-time rather than at runtime.
  3. Performance: Templates can lead to more efficient code because they are resolved at compile-time, eliminating the overhead associated with runtime polymorphism.
  4. Abstraction: They enable higher levels of abstraction, allowing programmers to focus on algorithms without worrying about specific data types.

These advantages contribute to more maintainable and robust codebases, which is crucial in large-scale software development.

Conclusion

Templates and generic programming are powerful features in C++17 that enhance the language’s flexibility and efficiency. By leveraging function templates, class templates, and template specialisation, we can write more abstract and reusable code. Moving forward, I anticipate that the continued evolution of templates, such as the introduction of concepts in C++20, will further simplify and strengthen generic programming practices.


References:

  • Stroustrup, B. (2013). The C++ Programming Language. Addison-Wesley.
  • ISO/IEC. (2017). International Standard ISO/IEC 14882:2017(E) Programming Language C++. International Organization for Standardization.