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
- Basic syntax
- Member definitions outside class
- Partial specialization
- Template aliases
- Practical generic containers
- Complete Stack/Array/traits
- Common errors
- Best practices
- 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 names →
typename/templatekeyword >>in nested templates → fine in C++11+ (was> >in C++03)- CTAD fails for default-constructed
Box bwhenTcan’t be deduced → writeBox<int> b
8. Best practices
- Prefer
typenamefor type parameters static_assertconstraintsusingforvalue_type, iterators inside containersif 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
.cppfor selected types to reduce compile time:
template class Stack<int>;
template class Stack<std::string>;
Related posts
- 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
| Topic | Detail |
|---|---|
| Syntax | template <typename T> class C { }; |
| Use | C<int> obj; (CTAD exceptions in C++17) |
| Members | Out-of-line definitions need template<typename T> and C<T>:: |
| Partial spec | Pattern-based specializations |
| Aliases | using 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.
Related posts
- Template specialization
- Exception basics