[C++] Introduction to Templates | How to Create Generic Functions and Classes

目次

Introduction

C++ Templates are a powerful feature that allows you to write generic code by parameterizing types. They not only generalize functions and classes but also dramatically improve the expressiveness of C++, enabling handling of variable-length arguments and defining special processing for specific types.

In this article, I will comprehensively explain everything from the basic usage of templates to more advanced and practical topics like variadic arguments and specialization.

1. Function Templates

Function templates allow you to define generic functions that are independent of types. The compiler automatically infers the actual type to be used based on the argument types.

Sample Code

template <typename T>
T get_max(T a, T b) {
    return (a > b) ? a : b;
}

// Generic lambda (since C++14) is also a form of function template
auto add = [](auto a, auto b) {
    return a + b;
};

Explanation: The get_max function works with any type (int, double, string, etc.) as long as the > operator is defined for it.

2. Class Templates

Class templates allow you to define generic classes independent of types. When using them, you generally need to explicitly specify the concrete type in < > (although type deduction is partially available since C++17).

Sample Code

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

int main() {
    Pair<int> p_int; // Instantiate with T as int
    p_int.first = 10;
    
    // Class Template Argument Deduction (CTAD) (since C++17)
    Pair p_double{3.14, 2.71}; // Automatically infers T is double
    return 0;
}

3. Variadic Templates

Since C++11, it is possible to accept an arbitrary number of template arguments. This allows you to implement functions with a variable number of arguments, like printf, in a type-safe manner.

Sample Code

#include <iostream>

// Base function to stop recursion
void print_all() {
    std::cout << std::endl;
}

// Recursive function using variadic templates
template <typename T, typename... Args>
void print_all(const T& first, const Args&... rest) {
    std::cout << first << " ";
    print_all(rest...); // Expand the remaining argument pack and call recursively
}

int main() {
    print_all(1, "hello", 3.14); // Passing 3 arguments of different types
    return 0;
}

4. Alias Templates

Since C++11, you can use using to give an alias to a template. This is very convenient for simplifying complex type names.

Sample Code

#include <vector>
#include <string>
#include <map>

// Give an alias StringMap<T> to std::map<std::string, T>
template <typename T>
using StringMap = std::map<std::string, T>;

int main() {
    // Same meaning as std::map<std::string, int>
    StringMap<int> user_scores;
    user_scores["Taro"] = 100;
    return 0;
}

5. Template Specialization

Use specialization when you want to provide a special implementation for a specific type that differs from the standard template implementation.

Sample Code

#include <iostream>
#include <vector>

// Generic Class Template
template <typename T>
class Container {
public:
    void print() { std::cout << "Generic Template" << std::endl; }
};

// 1. "Full Specialization" when T is int
template <>
class Container<int> {
public:
    void print() { std::cout << "Template Specialized for int" << std::endl; }
};

// 2. "Partial Specialization" when T is vector<U>
template <typename U>
class Container<std::vector<U>> {
public:
    void print() { std::cout << "Template Partially Specialized for vector" << std::endl; }
};


int main() {
    Container<double> c_double;
    Container<int> c_int;
    Container<std::vector<char>> c_vector;

    c_double.print();
    c_int.print();
    c_vector.print();
    
    return 0;
}

Explanation: Container calls a specific implementation depending on whether it is used with an int type or a vector type.

Summary

In this article, I comprehensively explained C++ templates, ranging from basic functions to advanced topics like variadic arguments and specialization.

Templates are a core feature supporting C++’s static polymorphism and generic programming, serving as the foundation for the STL (Standard Template Library). Understanding these features enables you to write highly reusable, type-safe, and efficient code.

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次