[ PROMPT_NODE_24601 ]
Cpp Pro – Templates
[ SKILL_DOCUMENTATION ]
# Template Metaprogramming
## Variadic Templates
```cpp
#include
#include
// Fold expressions (C++17)
template
auto sum(Args... args) {
return (args + ...); // Unary right fold
}
template
void print(Args&&... args) {
((std::cout << args << ' '), ...); // Binary left fold
std::cout << 'n';
}
// Recursive variadic template
template
void log(T&& value) {
std::cout << value << 'n';
}
template
void log(T&& first, Args&&... rest) {
std::cout << first << ", ";
log(std::forward(rest)...);
}
// Parameter pack expansion
template
struct TypeList {
static constexpr size_t size = sizeof...(Types);
};
template
auto make_tuple_advanced(Args&&... args) {
return std::tuple<std::decay_t...>(std::forward(args)...);
}
```
## SFINAE and if constexpr
```cpp
#include
// SFINAE with std::enable_if (older style)
template
std::enable_if_t<std::is_integral_v, T>
double_value(T value) {
return value * 2;
}
template
std::enable_if_t<std::is_floating_point_v, T>
double_value(T value) {
return value * 2.0;
}
// Modern: if constexpr (C++17)
template
auto process(T value) {
if constexpr (std::is_integral_v) {
return value * 2;
} else if constexpr (std::is_floating_point_v) {
return value * 2.0;
} else {
return value;
}
}
// Detection idiom
template
struct has_serialize : std::false_type {};
template
struct has_serialize<T, std::void_t<decltype(std::declval().serialize())>>
: std::true_type {};
template
constexpr bool has_serialize_v = has_serialize::value;
// Use with if constexpr
template
void save(const T& obj) {
if constexpr (has_serialize_v) {
obj.serialize();
} else {
// Default serialization
}
}
```
## Type Traits
```cpp
#include
// Custom type traits
template
struct remove_all_pointers {
using type = T;
};
template
struct remove_all_pointers {
using type = typename remove_all_pointers::type;
};
template
using remove_all_pointers_t = typename remove_all_pointers::type;
// Conditional types
template
struct conditional_type {
using type = T;
};
template
struct conditional_type {
using type = F;
};
// Compile-time type selection
template
struct best_integral_type {
using type = std::conditional_t<N <= 8, uint8_t,
std::conditional_t<N <= 16, uint16_t,
std::conditional_t<N >>;
};
// Check for member functions
template
struct has_reserve : std::false_type {};
template
struct has_reserve<T, std::void_t<decltype(std::declval().reserve(size_t{}))>>
: std::true_type {};
```
## CRTP (Curiously Recurring Template Pattern)
```cpp
// Static polymorphism with CRTP
template
class Shape {
public:
double area() const {
return static_cast(this)->area_impl();
}
void draw() const {
static_cast(this)->draw_impl();
}
};
class Circle : public Shape {
double radius_;
public:
Circle(double r) : radius_(r) {}
double area_impl() const {
return 3.14159 * radius_ * radius_;
}
void draw_impl() const {
std::cout << "Drawing circlen";
}
};
class Rectangle : public Shape {
double width_, height_;
public:
Rectangle(double w, double h) : width_(w), height_(h) {}
double area_impl() const {
return width_ * height_;
}
void draw_impl() const {
std::cout << "Drawing rectanglen";
}
};
// CRTP for mixin capabilities
template
class Printable {
public:
void print() const {
std::cout << static_cast(this)->to_string() << 'n';
}
};
class User : public Printable {
std::string name_;
public:
User(std::string name) : name_(std::move(name)) {}
std::string to_string() const {
return "User: " + name_;
}
};
```
## Template Template Parameters
```cpp
#include
#include
#include
// Template template parameter
template<typename T, template class Container>
class Stack {
Container<T, std::allocator> data_;
public:
void push(const T& value) {
data_.push_back(value);
}
T pop() {
T value = data_.back();
data_.pop_back();
return value;
}
size_t size() const {
return data_.size();
}
};
// Usage with different containers
Stack vector_stack;
Stack deque_stack;
Stack list_stack;
```
## Compile-Time Computation
```cpp
#include
// Compile-time factorial
constexpr int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
constexpr int fact_5 = factorial(5); // Computed at compile time
// Compile-time prime checking
constexpr bool is_prime(int n) {
if (n < 2) return false;
for (int i = 2; i * i <= n; ++i) {
if (n % i == 0) return false;
}
return true;
}
// Generate compile-time array of primes
template
constexpr auto generate_primes() {
std::array primes{};
int count = 0;
int candidate = 2;
while (count < N) {
if (is_prime(candidate)) {
primes[count++] = candidate;
}
++candidate;
}
return primes;
}
constexpr auto first_10_primes = generate_primes();
```
## Expression Templates
```cpp
// Lazy evaluation with expression templates
template
class VecExpression {
public:
double operator[](size_t i) const {
return static_cast(*this)[i];
}
size_t size() const {
return static_cast(*this).size();
}
};
class Vec : public VecExpression {
std::vector data_;
public:
Vec(size_t n) : data_(n) {}
double operator[](size_t i) const { return data_[i]; }
double& operator[](size_t i) { return data_[i]; }
size_t size() const { return data_.size(); }
// Evaluate expression template
template
Vec& operator=(const VecExpression& expr) {
for (size_t i = 0; i < size(); ++i) {
data_[i] = expr[i];
}
return *this;
}
};
// Binary operation expression
template
class VecSum : public VecExpression<VecSum> {
const E1& lhs_;
const E2& rhs_;
public:
VecSum(const E1& lhs, const E2& rhs) : lhs_(lhs), rhs_(rhs) {}
double operator[](size_t i) const {
return lhs_[i] + rhs_[i];
}
size_t size() const { return lhs_.size(); }
};
// Operator overload
template
VecSum operator+(const VecExpression& lhs,
const VecExpression& rhs) {
return VecSum(static_cast(lhs),
static_cast(rhs));
}
// Usage: a = b + c + d (no temporaries created!)
```
## Quick Reference
| Technique | Use Case | Performance |
|-----------|----------|-------------|
| Variadic Templates | Variable arguments | Zero overhead |
| SFINAE | Conditional compilation | Compile-time |
| if constexpr | Type-based branching | Zero overhead |
| CRTP | Static polymorphism | No vtable cost |
| Expression Templates | Lazy evaluation | Eliminates temps |
| Type Traits | Type introspection | Compile-time |
| Fold Expressions | Parameter pack ops | Optimal |
| Template Specialization | Type-specific impl | Zero overhead |
Source: claude-code-templates (MIT). See About Us for full credits.