Practical examples of C++ templates: function & class examples
Before worrying about theory, let’s look at a few real examples of C++ templates: function & class examples that mirror what you already do with plain functions and classes.
Here’s a simple function template that works for int, double, or any type that supports +:
// Function template: generic add
template <typename T>
T add(T a, T b) {
return a + b;
}
int main() {
int x = add(2, 3); // T deduced as int
double y = add(2.5, 3.1); // T deduced as double
}
And here’s a minimal class template that looks a lot like a stripped‑down std::pair:
// Class template: simple Pair
template <typename T, typename U>
class Pair {
public:
T first;
U second;
Pair(const T& f, const U& s) : first(f), second(s) {}
};
int main() {
Pair<int, std::string> p(42, "answer");
}
Those two snippets already cover the core idea behind most examples of C++ templates: function & class examples are just blueprints that the compiler uses to generate concrete code for specific types.
Function template examples: from trivial to actually useful
Let’s stay with function templates for a bit, because they’re the easiest way to build intuition.
Example 1: type‑agnostic max function
The classic beginner example of a function template is a generic max:
#include <iostream>
template <typename T>
const T& my_max(const T& a, const T& b) {
return (a < b) ? b : a;
}
int main() {
std::cout << my_max(3, 7) << '\n'; // int
std::cout << my_max(3.14, 2.71) << '\n'; // double
std::cout << my_max('a', 'z') << '\n'; // char
}
This is one of the best examples of a function template because it mirrors the standard library’s own std::max. You write the logic once, and the compiler generates a version for every type you use.
Example 2: function template with two different types
Sometimes your function naturally handles two different types, such as adding an int to a double:
#include <type_traits>
// Add two possibly different types and return the common type
template <typename T, typename U>
auto add_mixed(T a, U b) {
return a + b; // return type deduced by auto
}
int main() {
auto r1 = add_mixed(1, 2.5); // double
auto r2 = add_mixed(3u, 4LL); // long long (implementation-dependent)
}
This pattern shows up constantly in numeric and graphics code, where mixing integer and floating‑point types is normal.
Example 3: function template with non‑type parameter (array size)
Non‑type template parameters are underrated. They let you treat values (like array sizes) as template parameters:
#include <cstddef>
#include <iostream>
// Print a fixed-size C-style array
template <typename T, std::size_t N>
void print_array(const T (&arr)[N]) {
for (std::size_t i = 0; i < N; ++i) {
std::cout << arr[i] << (i + 1 < N ? ' ' : '\n');
}
}
int main() {
int nums[] = {1, 2, 3, 4};
print_array(nums); // N deduced as 4
}
This is a concrete example of a function template that avoids the classic bug of passing the wrong array size.
Example 4: C++20 constrained function template (concepts)
Modern C++ (C++20 and later) adds concepts, which let you constrain templates in a readable way:
#include <concepts>
// Only accept arithmetic types
template <std::integral T>
T gcd(T a, T b) {
while (b != 0) {
T t = b;
b = a % b;
a = t;
}
return a;
}
int main() {
auto g = gcd(48, 18); // OK
// auto bad = gcd(4.5, 1.5); // error: not integral
}
This is a modern example of C++ templates: function & class examples using language features that are standard as of 2024 and widely supported in compilers like GCC, Clang, and MSVC.
For the C++20 standard text and concepts reference, see the ISO C++ committee’s public drafts hosted via cppreference.com.
Class template examples: containers, wrappers, and policies
Function templates are great, but class templates are where C++ really leans into generic programming. Many of the best examples of C++ templates: function & class examples live in the standard library itself: std::vector<T>, std::map<Key, T>, std::optional<T>, and more.
Example 5: a minimal Vector2 math type
Game and graphics engines nearly always define template vector types:
template <typename T>
class Vector2 {
public:
T x{};
T y{};
Vector2() = default;
Vector2(T x_, T y_) : x(x_), y(y_) {}
Vector2 operator+(const Vector2& other) const {
return {x + other.x, y + other.y};
}
};
int main() {
Vector2<float> pos(1.0f, 2.0f);
Vector2<float> vel(0.5f, 0.0f);
auto next = pos + vel;
}
This single class template gives you Vector2<float>, Vector2<double>, or even Vector2<int> without repeating code.
Example 6: type‑safe ID wrapper
A very practical example of a class template is a strong typedef or ID wrapper:
#include <cstdint>
// Distinguish between different ID types at compile time
template <typename Tag>
class Id {
public:
using value_type = std::uint32_t;
explicit Id(value_type v = 0) : value_(v) {}
value_type value() const { return value_; }
friend bool operator==(Id a, Id b) { return a.value_ == b.value_; }
private:
value_type value_;
};
struct UserTag {};
struct OrderTag {};
using UserId = Id<UserTag>;
using OrderId = Id<OrderTag>;
int main() {
UserId u(1);
OrderId o(1);
// u == o; // compile-time error: different types
}
This pattern shows how examples of C++ templates: function & class examples can actually prevent bugs by making invalid comparisons impossible.
Example 7: small fixed‑size buffer with non‑type parameter
Here’s a class template that uses a non‑type template parameter to control capacity at compile time:
#include <cstddef>
#include <stdexcept>
// Simple fixed-size ring buffer
template <typename T, std::size_t Capacity>
class RingBuffer {
public:
bool push(const T& value) {
if (size_ == Capacity) return false;
data_[(head_ + size_) % Capacity] = value;
++size_;
return true;
}
T pop() {
if (size_ == 0) throw std::out_of_range("empty");
T value = data_[head_];
head_ = (head_ + 1) % Capacity;
--size_;
return value;
}
std::size_t size() const { return size_; }
private:
T data_[Capacity]{};
std::size_t head_ = 0;
std::size_t size_ = 0;
};
int main() {
RingBuffer<int, 8> rb; // capacity known at compile time
}
Embedded systems and high‑performance trading codebases are full of real examples like this, where compile‑time sizes matter for performance and predictability.
Example 8: policy‑based logging class template
Templates also shine when you want to inject behavior, not just types. A common pattern is a logger that takes a policy class as a template parameter:
#include <iostream>
#include <string>
struct ConsolePolicy {
void write(const std::string& msg) {
std::cout << msg << '\n';
}
};
struct NullPolicy {
void write(const std::string&) {
// no-op
}
};
// Logger template parameterized by policy type
template <typename Policy>
class Logger {
public:
void log(const std::string& msg) {
policy_.write(msg);
}
private:
Policy policy_{};
};
int main() {
Logger<ConsolePolicy> console_logger;
Logger<NullPolicy> disabled_logger;
console_logger.log("Hello, templates!");
disabled_logger.log("This goes nowhere");
}
This is one of the best examples of C++ templates: function & class examples where templates replace inheritance for customization.
Template specialization and partial specialization examples
Sometimes you want a generic template and a special case for a specific type. That’s where specialization comes in.
Example 9: full specialization for bool
Imagine a simple storage wrapper where bool gets a different representation:
// Primary template
template <typename T>
class Storage {
public:
void set(const T& value) { value_ = value; }
const T& get() const { return value_; }
private:
T value_{};
};
// Full specialization for bool
template <>
class Storage<bool> {
public:
void set(bool value) { value_ = value; }
bool get() const { return value_; }
private:
unsigned char value_ : 1; // store as single bit
};
int main() {
Storage<int> si;
Storage<bool> sb;
}
This mirrors what std::vector<bool> famously does (for better or worse) in the standard library.
Example 10: partial specialization for pointer types
Partial specialization lets you tweak behavior for a family of types, such as all pointers:
#include <cstddef>
// Primary template
template <typename T>
struct TypeInfo {
static constexpr bool is_pointer = false;
};
// Partial specialization for pointer types
template <typename T>
struct TypeInfo<T*> {
static constexpr bool is_pointer = true;
};
int main() {
static_assert(!TypeInfo<int>::is_pointer);
static_assert(TypeInfo<int*>::is_pointer);
}
This is a simple example of how the standard library builds type traits like std::is_pointer and std::is_integral.
For a deeper reference on specialization and traits, the C++ Core Guidelines maintained by the ISO C++ community and Microsoft are a good starting point: C++ Core Guidelines.
How the standard library uses templates (and why you should care)
If you’re looking for real examples of C++ templates: function & class examples in production‑grade code, you don’t have to look further than the standard library.
Some everyday tools that are themselves templates:
std::vector<T>– dynamic array for anyTstd::array<T, N>– fixed‑size array with compile‑time lengthstd::optional<T>– maybe‑present value, heavily used in modern C++ APIsstd::function<R(Args...)>– type‑erased callable wrapperstd::unique_ptr<T>/std::shared_ptr<T>– smart pointers managing ownership
Each of these is a polished example of C++ templates: function & class examples that have been battle‑tested in real software. Reading how they’re specified (see cppreference.com) is a surprisingly good way to pick up patterns and idioms.
Industry surveys, including the JetBrains “C++ Ecosystem” reports for 2023–2024, show that a large majority of C++ developers target C++17 or later. That means template‑heavy features like std::optional, std::variant, and std::filesystem are now mainstream, not exotic.
Modern tips for working with template heavy code (2024–2025)
As of 2024–2025, three trends dominate real examples of C++ templates: function & class examples in new codebases:
- Use
autogenerously for return types and local variables when the exact type isn’t part of your API contract. It keeps template code readable. - Adopt concepts to make error messages sane. A constrained template with
std::integralor a custom concept is far easier to debug than a 50‑line substitution failure. - Lean on standard type traits like
std::is_same_v,std::enable_if_t, andstd::conditional_tinstead of rolling your own metaprogramming from scratch.
For structured learning, many universities host modern C++ material; for example, MIT’s OpenCourseWare and similar platforms often include C++ template content alongside systems programming courses: MIT OpenCourseWare.
FAQ: short answers with more examples
What are some simple examples of C++ templates I can memorize?
Two minimal patterns worth memorizing are:
// Function template
template <typename T>
T square(T x) { return x * x; }
// Class template
template <typename T>
class Box {
public:
explicit Box(const T& value) : value_(value) {}
const T& get() const { return value_; }
private:
T value_;
};
These examples of C++ templates: function & class examples map almost directly to how std::optional<T> or std::vector<T> are written.
Can you show an example of mixing templates and lambdas?
Yes. Lambdas themselves are templates under the hood, but you can also write a function template that takes a lambda:
#include <vector>
template <typename Container, typename Func>
void for_each_indexed(Container& c, Func f) {
std::size_t i = 0;
for (auto& elem : c) {
f(i++, elem);
}
}
int main() {
std::vector<int> v{1, 2, 3};
for_each_indexed(v, [](std::size_t i, int& x) {
x += static_cast<int>(i);
});
}
This is a practical example of a function template that works with any container and any callable.
Where can I see more real examples of C++ templates: function & class examples?
Good places to study real‑world patterns:
- The C++ standard library reference at cppreference.com
- The C++ Core Guidelines (backed by the ISO C++ committee and Microsoft): https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
- University course material from major CS programs, such as MIT OpenCourseWare or similar platforms that share C++ lectures and notes
Reading and imitating these sources will give you more grounded examples of C++ templates: function & class examples than any toy snippet can.
Related Topics
Practical examples of polymorphism in C++: function overloading
Best examples of dynamic memory allocation in C++: new and delete
Practical examples of C# variable declaration and initialization examples
Modern examples of C++ operator overloading: custom operators examples that actually matter
Best examples of C# conditional statements: examples & explanations
Real‑world examples of C# exception handling: 3 practical patterns every developer should know
Explore More C++ Code Snippets
Discover more examples and insights in this category.
View All C++ Code Snippets