C++ Class Templates | Generic Containers and Partial Specialization

C++ Class Templates | Generic Containers and Partial Specialization

이 글의 핵심

Class templates: template<typename T>, member definitions outside the class, partial specialization, aliases, Stack/Array examples, and common template errors.

Introduction: Int stack, double stack—copy/paste forever?

Stop duplicating Stack for every type

You wrote IntStack, DoubleStack, same logic—only T differs. Class templates are the cookie cutter: one pattern, many baked shapes. You write Stack<int>, Stack<double>, Stack<std::string> once; the compiler instantiates a concrete class at each use.

// g++ -std=c++17 -o stack_tpl stack_tpl.cpp && ./stack_tpl
#include <vector>
#include <iostream>
#include <string>
#include <stdexcept>

template <typename T>
class Stack {
    std::vector<T> data;
public:
    void push(const T& value) { data.push_back(value); }
    T pop() {
        if (empty()) throw std::logic_error("Stack is empty");
        T value = data.back();
        data.pop_back();
        return value;
    }
    bool empty() const { return data.empty(); }
    size_t size() const { return data.size(); }
};

int main() {
    Stack<int> intStack;
    intStack.push(10);
    intStack.push(20);
    std::cout << intStack.pop() << "\n";
    Stack<std::string> strStack;
    strStack.push("hello");
    strStack.push("world");
    std::cout << strStack.pop() << "\n";
    return 0;
}

Unlike function templates, you usually name the template arguments explicitly: Stack<int>. C++17 CTAD can deduce in some cases from constructors.

flowchart TB
  subgraph template["Template definition"]
    T["template <typename T>\nclass Stack"]
  end
  subgraph instances["Instantiated types"]
    I1["Stack<int>"]
    I2["Stack<double>"]
    I3["Stack<std::string>"]
  end
  T -->|T=int| I1
  T -->|T=double| I2
  T -->|T=std::string| I3

Table of contents

  1. Basic syntax
  2. Member definitions outside class
  3. Partial specialization
  4. Template aliases
  5. Practical generic containers
  6. Complete Stack/Array/traits
  7. Common errors
  8. Best practices
  9. Production patterns

1. Basic syntax

template <typename T>
class Box {
    T value;
public:
    Box(const T& v) : value(v) {}
    T get() const { return value; }
    void set(const T& v) { value = v; }
};

Multiple parameters:

template <typename K, typename V>
class KeyValue { /* ... */ };

Default template arguments:

template <typename T, typename Container = std::vector<T>>
class Stack { /* ... */ };

2. Out-of-line member definitions

template <typename T>
void Container<T>::set(const T& v) {
    value = v;
}

Templates: definitions typically stay in headers (same TU) to avoid link errors.

Static data members:

template <typename T>
int Counter<T>::count = 0;

3. Partial specialization

Specialize for patterns (e.g. T*, T[], Pair<T,T>)—not in the primary template.

Note: A common pattern uses SmartPtr<T[]>-style partial specialization for array delete semantics—match your design to delete vs delete[].


4. Template aliases

template <typename T>
using Vec = std::vector<T>;

template <typename K, typename V>
using Map = std::unordered_map<K, V>;

template <typename T>
using StringMap = std::unordered_map<std::string, T>;

7. Common errors

  • Undefined reference to template member defined only in .cpp → put definition in header or explicit instantiation
  • Dependent namestypename / template keyword
  • >> in nested templates → fine in C++11+ (was > > in C++03)
  • CTAD fails for default-constructed Box b when T can’t be deduced → write Box<int> b

8. Best practices

  • Prefer typename for type parameters
  • static_assert constraints
  • using for value_type, iterators inside containers
  • if constexpr (C++17) for type-specific branches

9. Production patterns

  • CRTP for static polymorphism
  • Policy-based design (container type as template parameter)
  • Explicit instantiation in .cpp for selected types to reduce compile time:
template class Stack<int>;
template class Stack<std::string>;

  • Template basics
  • Variadic templates
  • auto and decltype

Keywords

C++ class template, template class, partial specialization, generic container, template alias, type traits, CRTP, policy design

Summary

TopicDetail
Syntaxtemplate <typename T> class C { };
UseC<int> obj; (CTAD exceptions in C++17)
MembersOut-of-line definitions need template<typename T> and C<T>::
Partial specPattern-based specializations
Aliasesusing Alias = Template<T>;

One-line summary: One class template replaces many copy-pasted classes; specialize patterns; keep definitions visible to the compiler.

Next: Variadic templates #9-3

FAQ

When is this useful?

A. Building reusable containers, wrappers, and type-safe APIs—core of STL-style design.

Read first?

A. Template basics, series index.


  • Template specialization
  • Exception basics