Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. C++ Dictionary
  3. Template Class

Template Class

C++ class templates define a generic class that accepts types as parameters. Containers (arrays, stacks, queues, etc.) and data structures can be implemented in a type-independent way, eliminating the need to hand-write separate int, double, and std::string versions. The standard library's std::vector and std::stack are also implemented as class templates.

Syntax

// ========================================
// Basic class template syntax
// ========================================

// Declare type parameter T with the template keyword
template <typename T>
class MyContainer {
private:
    T data;  // Member variable of type T

public:
    // T can also be used in the constructor
    MyContainer(T value) : data(value) {}

    // T can be used as the return type and parameter type of methods
    T get() const { return data; }
    void set(T value) { data = value; }
};

// Instantiation: specify the concrete type inside <>
MyContainer<int>         intBox(42);        // Instantiated with T = int
MyContainer<std::string> strBox("hello");   // Instantiated with T = std::string

// ----------------------------------------
// Class template with multiple type parameters
// ----------------------------------------
template <typename K, typename V>
class Pair {
public:
    K key;
    V value;
    Pair(K k, V v) : key(k), value(v) {}
};

Pair<std::string, int> p("score", 100);

// ----------------------------------------
// Default type argument (C++11 and later)
// ----------------------------------------
template <typename T = int>
class DefaultContainer {
    T data;
};

DefaultContainer<> dc;  // Treated as T = int

Syntax Reference

Syntax / ConceptDescription
template <typename T> class Name { };Declares a class template with type parameter T. Using class instead of typename is equivalent.
ClassName<Type>Instantiates the class template with a specific type, such as <int> or <std::string>.
Multiple type parametersMultiple type parameters can be declared as in template <typename K, typename V>. Useful for implementing pairs or map-like structures with separate key and value types.
Default type argumentA default type can be specified as in template <typename T = int>. The default type is used when <> is left empty.
Full specialization of a class templatetemplate<> class Name<SpecificType> { }; provides a type-specific implementation. The specialization takes priority over the generic version.
Partial specializationA different implementation can be defined for a subset of patterns, such as pointer types: template <typename T> class Name<T*> { };.
Non-type template parameterValues can be used as parameters: template <typename T, int N>. Commonly used for fixed-size array containers.

Sample Code

jujutsu_stack.cpp
// ========================================
// jujutsu_stack.cpp — class template sample
// Uses Jujutsu Kaisen characters to demonstrate
// implementing and using a generic stack container
// ========================================

#include <iostream>
#include <string>
#include <stdexcept>

// ========================================
// Class template: Stack<T>
// A fixed-size stack that can hold any type T
// Non-type template parameter N sets the maximum size
// ========================================
template <typename T, int N = 10>
class Stack {
private:
    T    items[N];  // Array of type T (fixed size N)
    int  top;       // Index of the next push position

public:
    // Constructor: initializes the stack as empty
    Stack() : top(0) {}

    // push(): pushes a value onto the top of the stack
    void push(const T& item) {
        if (top >= N) {
            throw std::overflow_error("Stack is full.");
        }
        items[top++] = item;
    }

    // pop(): removes and returns the top value
    T pop() {
        if (top <= 0) {
            throw std::underflow_error("Stack is empty.");
        }
        return items[--top];
    }

    // peek(): returns the top value without removing it
    const T& peek() const {
        if (top <= 0) {
            throw std::underflow_error("Stack is empty.");
        }
        return items[top - 1];
    }

    // isEmpty(): returns true if the stack is empty
    bool isEmpty() const { return top == 0; }

    // size(): returns the current number of elements
    int size() const { return top; }
};

// ========================================
// Class template: Pair<K, V>
// Holds two values of different types together
// ========================================
template <typename K, typename V>
class Pair {
public:
    K key;
    V value;

    Pair(const K& k, const V& v) : key(k), value(v) {}

    void display() const {
        std::cout << key << ": " << value << std::endl;
    }
};

// ========================================
// Full specialization for std::string: Stack<std::string, N>
// Adds a printAll() method only for the string stack
// ========================================
template <int N>
class Stack<std::string, N> {
private:
    std::string items[N];
    int         top;

public:
    Stack() : top(0) {}

    void push(const std::string& item) {
        if (top >= N) {
            throw std::overflow_error("Stack is full.");
        }
        items[top++] = item;
    }

    std::string pop() {
        if (top <= 0) {
            throw std::underflow_error("Stack is empty.");
        }
        return items[--top];
    }

    bool isEmpty() const { return top == 0; }
    int  size()    const { return top; }

    // Additional method exclusive to the string specialization
    // Prints all elements from bottom to top
    void printAll() const {
        std::cout << "--- Stack contents (bottom to top) ---" << std::endl;
        for (int i = 0; i < top; i++) {
            std::cout << "  [" << i << "] " << items[i] << std::endl;
        }
    }
};

int main() {
    // ----------------------------------------
    // Stack<int> — manage technique power (int) on the stack
    // Uses default N = 10
    // ----------------------------------------
    std::cout << "=== Cursed technique power stack (int) ===" << std::endl;

    Stack<int> powerStack;
    powerStack.push(3800);  // Itadori Yuji's Black Flash power
    powerStack.push(2900);  // Fushiguro Megumi's shikigami power
    powerStack.push(4200);  // Gojo Satoru's Infinity technique power
    powerStack.push(3100);  // Nanami Kento's Ratio Technique power

    std::cout << "Elements pushed: " << powerStack.size() << std::endl;
    std::cout << "Top value (Nanami Kento): " << powerStack.peek() << std::endl;

    std::cout << "Pop order (last in, first out):" << std::endl;
    while (!powerStack.isEmpty()) {
        std::cout << "  " << powerStack.pop() << std::endl;
    }

    std::cout << std::endl;

    // ----------------------------------------
    // Stack<double> — manage cursed energy remaining (double)
    // ----------------------------------------
    std::cout << "=== Cursed energy remaining stack (double) ===" << std::endl;

    Stack<double, 5> curseStack;  // Maximum 5 entries
    curseStack.push(98.5);   // Itadori Yuji's remaining energy (%)
    curseStack.push(87.2);   // Fushiguro Megumi's remaining energy
    curseStack.push(100.0);  // Gojo Satoru's remaining energy

    std::cout << "Remaining energy (starting from Gojo Satoru):" << std::endl;
    while (!curseStack.isEmpty()) {
        std::cout << "  " << curseStack.pop() << " %" << std::endl;
    }

    std::cout << std::endl;

    // ----------------------------------------
    // Stack<std::string> — uses the string specialization
    // printAll() is available here
    // ----------------------------------------
    std::cout << "=== Sortie order stack (string specialization) ===" << std::endl;

    Stack<std::string, 5> nameStack;
    nameStack.push("Nanami Kento");
    nameStack.push("Kugisaki Nobara");
    nameStack.push("Fushiguro Megumi");
    nameStack.push("Itadori Yuji");

    nameStack.printAll();  // Method exclusive to the string specialization

    std::cout << "Popping from the top:" << std::endl;
    std::cout << "  " << nameStack.pop() << " sorties first." << std::endl;
    std::cout << "  " << nameStack.pop() << " sorties next." << std::endl;

    std::cout << std::endl;

    // ----------------------------------------
    // Pair<K, V> — holds two values as a pair
    // ----------------------------------------
    std::cout << "=== Character and grade pairs ===" << std::endl;

    Pair<std::string, std::string> p1("Itadori Yuji",    "Grade 1 (special case)");
    Pair<std::string, std::string> p2("Gojo Satoru",     "Special Grade");
    Pair<std::string, int>         p3("Kugisaki Nobara", 3);  // K=string, V=int
    Pair<std::string, double>      p4("Nanami Kento",    1.5); // Between Grade 1 and Special Grade

    p1.display();
    p2.display();

    std::cout << p3.key << ": Semi-Grade 1 (sorcerer rank " << p3.value << ")" << std::endl;
    std::cout << p4.key << ": Grade 1 sorcerer (proficiency " << p4.value << ")" << std::endl;

    return 0;
}
# Compile
g++ -std=c++11 jujutsu_stack.cpp -o jujutsu_stack

# Run
./jujutsu_stack
=== Cursed technique power stack (int) ===
Elements pushed: 4
Top value (Nanami Kento): 3100
Pop order (last in, first out):
  3100
  4200
  2900
  3800

=== Cursed energy remaining stack (double) ===
Remaining energy (starting from Gojo Satoru):
  100 %
  87.2 %
  98.5 %

=== Sortie order stack (string specialization) ===
--- Stack contents (bottom to top) ---
  [0] Nanami Kento
  [1] Kugisaki Nobara
  [2] Fushiguro Megumi
  [3] Itadori Yuji
Popping from the top:
  Itadori Yuji sorties first.
  Fushiguro Megumi sorties next.

=== Character and grade pairs ===
Itadori Yuji: Grade 1 (special case)
Gojo Satoru: Special Grade
Kugisaki Nobara: Semi-Grade 1 (sorcerer rank 3)
Nanami Kento: Grade 1 sorcerer (proficiency 1.5)

Common Mistakes

Putting member function definitions of a class template in a .cpp file causes linker errors. Because templates generate type-specific code at compile time, the compiler must be able to see the member function implementations when it processes the header file.

stack.h (NG pattern)
// NG: Member function definitions are in a .cpp file (causes linker errors)
// stack.h
template <typename T>
class Stack {
public:
    void push(const T& item);  // Only the declaration is in the header
    T    pop();
private:
    T   items[10];
    int top = 0;
};
stack.cpp (NG pattern)
// NG: Definitions are in .cpp — callers that use Stack<int> cannot link
#include "stack.h"

template <typename T>
void Stack<T>::push(const T& item) {
    items[top++] = item;
}

template <typename T>
T Stack<T>::pop() {
    return items[--top];
}

The basic rule is to write both declarations and definitions of class template member functions in the header file.

stack_ok.h (OK pattern)
// OK: Write both declarations and definitions in the header
// stack_ok.h
template <typename T>
class Stack {
public:
    void push(const T& item) {
        items[top++] = item;  // Definition written directly in the header
    }
    T pop() {
        return items[--top];
    }
    bool isEmpty() const { return top == 0; }
private:
    T   items[10];
    int top = 0;
};
g++ -std=c++11 main.cpp -o main
./main

If you need to keep the declaration and definition in separate files, a common approach is to use an extension such as .tpp or .ipp for the implementation file and include it at the end of the header with #include "stack.tpp".

Overview

Class templates are declared with template <typename T> to define a generic class that accepts types as parameters. Each time the template is instantiated — as Stack<int> or Stack<std::string> — the compiler automatically generates type-specific class code. This eliminates the need to duplicate int, double, and std::string versions by hand. Multiple type parameters are allowed, enabling Pair<K, V>-style designs with separate key and value types. Combining non-type template parameters (template <typename T, int N>) allows array sizes to be handled safely as compile-time constants. When a specific type needs different behavior, defining a full specialization (template <int N> class Stack<std::string, N> { };) gives it priority over the generic version. Class templates, alongside function templates, form the backbone of the STL (Standard Template Library) — std::vector, std::stack, and std::map are all implemented as class templates.

If you find any errors or copyright issues, please .