Use when creating generic and type-safe C++ libraries with templates, SFINAE, concepts, and compile-time metaprogramming.
Creates generic, type-safe C++ libraries using templates, SFINAE, concepts, and compile-time metaprogramming. Use when building reusable C++ code that needs compile-time type checking and generic algorithms.
/plugin marketplace add TheBushidoCollective/han/plugin install jutsu-mise@hanThis skill is limited to using the following tools:
Master C++ templates, template metaprogramming, SFINAE, concepts, and compile-time computation. This skill enables you to create generic, type-safe, and highly efficient C++ libraries with compile-time guarantees.
// Simple function template
template<typename T>
T max(T a, T b) {
return (a > b) ? a : b;
}
// Usage
int i = max(10, 20); // T = int
double d = max(3.14, 2.71); // T = double
// auto x = max(10, 3.14); // ERROR: can't deduce T
// Multiple template parameters
template<typename T, typename U>
auto add(T a, U b) -> decltype(a + b) {
return a + b;
}
auto result = add(5, 3.14); // T = int, U = double, returns double
// C++14: simpler return type deduction
template<typename T, typename U>
auto multiply(T a, U b) {
return a * b;
}
// Primary template
template<typename T>
T absolute(T value) {
return (value < 0) ? -value : value;
}
// Full specialization for const char*
template<>
const char* absolute<const char*>(const char* value) {
return value; // Strings don't have absolute value
}
// Full specialization for std::string
template<>
std::string absolute<std::string>(std::string value) {
return value;
}
// Usage
int a = absolute(-5); // Uses primary template
const char* b = absolute("test"); // Uses const char* specialization
// Overload 1: Generic template
template<typename T>
void print(T value) {
std::cout << "Generic: " << value << std::endl;
}
// Overload 2: Pointer specialization
template<typename T>
void print(T* ptr) {
std::cout << "Pointer: " << *ptr << std::endl;
}
// Overload 3: Non-template overload
void print(const char* str) {
std::cout << "String: " << str << std::endl;
}
// Usage
int x = 42;
print(x); // Overload 1
print(&x); // Overload 2
print("hello"); // Overload 3 (exact match preferred)
// Simple class template
template<typename T>
class Container {
T value;
public:
Container(T v) : value(v) {}
T get() const { return value; }
void set(T v) { value = v; }
};
// Usage
Container<int> intContainer(42);
Container<std::string> strContainer("hello");
// Multiple template parameters
template<typename K, typename V>
class KeyValuePair {
K key;
V value;
public:
KeyValuePair(K k, V v) : key(k), value(v) {}
K getKey() const { return key; }
V getValue() const { return value; }
};
KeyValuePair<std::string, int> pair("answer", 42);
template<typename T>
class Array {
T* data;
size_t size;
public:
Array(size_t s) : size(s), data(new T[s]) {}
~Array() { delete[] data; }
// Template member function
template<typename Func>
void forEach(Func func) {
for (size_t i = 0; i < size; ++i) {
func(data[i]);
}
}
// Template conversion operator
template<typename U>
operator Array<U>() const {
Array<U> result(size);
for (size_t i = 0; i < size; ++i) {
result.data[i] = static_cast<U>(data[i]);
}
return result;
}
};
// Usage
Array<int> arr(5);
arr.forEach([](int& x) { x *= 2; });
// Primary template
template<typename T>
class Storage {
T data;
public:
Storage(T d) : data(d) {}
T get() const { return data; }
};
// Full specialization for pointers
template<typename T>
class Storage<T*> {
T* data;
public:
Storage(T* d) : data(d) {}
T* get() const { return data; }
T& operator*() { return *data; }
};
// Full specialization for bool (bit optimization)
template<>
class Storage<bool> {
unsigned char data : 1;
public:
Storage(bool d) : data(d) {}
bool get() const { return data; }
};
// Primary template
template<typename T, typename U>
class Pair {
public:
T first;
U second;
void info() { std::cout << "Generic pair" << std::endl; }
};
// Partial specialization: both types the same
template<typename T>
class Pair<T, T> {
public:
T first;
T second;
void info() { std::cout << "Same type pair" << std::endl; }
};
// Partial specialization: second type is pointer
template<typename T, typename U>
class Pair<T, U*> {
public:
T first;
U* second;
void info() { std::cout << "Second is pointer" << std::endl; }
};
// Usage
Pair<int, double> p1; // Generic
Pair<int, int> p2; // Same type
Pair<int, double*> p3; // Second is pointer
// Single type parameter
template<typename T>
class Vector {
T* data;
};
// Multiple type parameters
template<typename T, typename Allocator>
class CustomVector {
T* data;
Allocator alloc;
};
// Default type parameters
template<typename T, typename Compare = std::less<T>>
class Set {
Compare comp;
public:
bool less(const T& a, const T& b) {
return comp(a, b);
}
};
// Integer non-type parameter
template<typename T, size_t N>
class Array {
T data[N];
public:
constexpr size_t size() const { return N; }
T& operator[](size_t i) { return data[i]; }
const T& operator[](size_t i) const { return data[i]; }
};
Array<int, 10> arr1; // Array of 10 ints
Array<double, 5> arr2; // Array of 5 doubles
// Bool non-type parameter
template<typename T, bool IsSorted>
class Container {
public:
void insert(T value) {
if constexpr (IsSorted) {
insert_sorted(value);
} else {
insert_unsorted(value);
}
}
private:
void insert_sorted(T value) { /* ... */ }
void insert_unsorted(T value) { /* ... */ }
};
// Pointer non-type parameter (C++17)
template<auto* Ptr>
class StaticWrapper {
public:
auto& get() { return *Ptr; }
};
// Template template parameter
template<typename T, template<typename> class Container>
class Stack {
Container<T> data;
public:
void push(const T& value) {
data.push_back(value);
}
T pop() {
T value = data.back();
data.pop_back();
return value;
}
};
// Usage
Stack<int, std::vector> intStack;
Stack<double, std::deque> doubleStack;
// With multiple parameters
template<typename T,
template<typename, typename> class Container,
typename Allocator = std::allocator<T>>
class AdvancedStack {
Container<T, Allocator> data;
};
// Basic variadic template
template<typename... Args>
void print(Args... args) {
(std::cout << ... << args) << std::endl; // C++17 fold expression
}
print(1, 2, 3, "hello", 3.14);
// Get pack size
template<typename... Args>
constexpr size_t count(Args... args) {
return sizeof...(args);
}
size_t n = count(1, 2, 3, 4); // 4
// Recursive parameter pack processing (pre-C++17)
template<typename T>
void print_recursive(T value) {
std::cout << value << std::endl;
}
template<typename T, typename... Args>
void print_recursive(T first, Args... rest) {
std::cout << first << " ";
print_recursive(rest...); // Recursive call
}
// Unary right fold: (args op ...)
template<typename... Args>
auto sum(Args... args) {
return (args + ...);
}
auto result = sum(1, 2, 3, 4, 5); // 15
// Unary left fold: (... op args)
template<typename... Args>
auto sum_left(Args... args) {
return (... + args);
}
// Binary right fold: (args op ... op init)
template<typename... Args>
auto sum_with_init(Args... args) {
return (args + ... + 0);
}
// Binary left fold: (init op ... op args)
template<typename... Args>
auto multiply_with_init(Args... args) {
return (1 * ... * args);
}
// Logical fold expressions
template<typename... Args>
bool all_true(Args... args) {
return (args && ...);
}
template<typename... Args>
bool any_true(Args... args) {
return (args || ...);
}
// Comma fold for side effects
template<typename... Args>
void print_all(Args... args) {
(std::cout << ... << args) << std::endl;
}
// Tuple-like class
template<typename... Types>
class Tuple;
// Base case: empty tuple
template<>
class Tuple<> {};
// Recursive case
template<typename Head, typename... Tail>
class Tuple<Head, Tail...> : private Tuple<Tail...> {
Head value;
public:
Tuple(Head h, Tail... t) : Tuple<Tail...>(t...), value(h) {}
Head& head() { return value; }
Tuple<Tail...>& tail() { return *this; }
};
// Usage
Tuple<int, double, std::string> t(42, 3.14, "hello");
// Variadic template with perfect forwarding
template<typename... Args>
auto make_unique_custom(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
// Enable if type has begin() method
template<typename T>
auto process(T container) -> decltype(container.begin(), void()) {
std::cout << "Container with begin()" << std::endl;
}
// Enable if type is arithmetic
template<typename T>
auto process(T value)
-> typename std::enable_if<std::is_arithmetic<T>::value>::type {
std::cout << "Arithmetic type" << std::endl;
}
// Usage
std::vector<int> vec;
process(vec); // First overload
process(42); // Second overload
// Enable function for integral types only
template<typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type
increment(T value) {
return value + 1;
}
// C++14: cleaner syntax with enable_if_t
template<typename T>
std::enable_if_t<std::is_integral<T>::value, T>
decrement(T value) {
return value - 1;
}
// As template parameter (C++14)
template<typename T, typename = std::enable_if_t<std::is_floating_point<T>::value>>
T half(T value) {
return value / 2;
}
// Multiple enable_if conditions
template<typename T>
std::enable_if_t<std::is_pointer<T>::value &&
!std::is_const<std::remove_pointer_t<T>>::value, void>
modify(T ptr) {
*ptr = {};
}
// Implementation functions with tags
template<typename Iterator>
void advance_impl(Iterator& it, int n, std::random_access_iterator_tag) {
it += n; // O(1) for random access
}
template<typename Iterator>
void advance_impl(Iterator& it, int n, std::input_iterator_tag) {
while (n--) ++it; // O(n) for input iterators
}
// Dispatch function
template<typename Iterator>
void advance(Iterator& it, int n) {
advance_impl(it, n,
typename std::iterator_traits<Iterator>::iterator_category());
}
// Replaces many SFINAE use cases
template<typename T>
auto process(T value) {
if constexpr (std::is_integral_v<T>) {
return value * 2;
} else if constexpr (std::is_floating_point_v<T>) {
return value * 3.14;
} else if constexpr (std::is_pointer_v<T>) {
return *value;
} else {
return value;
}
}
// Variadic template with if constexpr
template<typename T, typename... Args>
void print(T first, Args... rest) {
std::cout << first;
if constexpr (sizeof...(rest) > 0) {
std::cout << ", ";
print(rest...);
} else {
std::cout << std::endl;
}
}
#include <concepts>
// Simple concept
template<typename T>
concept Integral = std::is_integral_v<T>;
// Concept with requires expression
template<typename T>
concept Incrementable = requires(T x) {
{ ++x } -> std::same_as<T&>;
{ x++ } -> std::same_as<T>;
};
// Compound concept
template<typename T>
concept Number = std::is_arithmetic_v<T>;
template<typename T>
concept SignedNumber = Number<T> && std::is_signed_v<T>;
// Concept with multiple requirements
template<typename T>
concept Container = requires(T c) {
typename T::value_type;
typename T::iterator;
{ c.begin() } -> std::same_as<typename T::iterator>;
{ c.end() } -> std::same_as<typename T::iterator>;
{ c.size() } -> std::convertible_to<std::size_t>;
};
// Constrain function template
template<Integral T>
T add(T a, T b) {
return a + b;
}
// Requires clause
template<typename T>
requires Integral<T>
T multiply(T a, T b) {
return a * b;
}
// Abbreviated function template (C++20)
auto divide(Integral auto a, Integral auto b) {
return a / b;
}
// Constrain class template
template<Container C>
class Processor {
C container;
public:
void process() {
for (auto& item : container) {
// Process item
}
}
};
// Multiple constraints
template<typename T>
requires std::is_arithmetic_v<T> && std::is_signed_v<T>
T absolute(T value) {
return value < 0 ? -value : value;
}
// Different implementations based on concepts
template<typename T>
void process(T value) {
if constexpr (Integral<T>) {
std::cout << "Processing integer: " << value << std::endl;
} else if constexpr (std::floating_point<T>) {
std::cout << "Processing float: " << value << std::endl;
} else {
std::cout << "Processing other: " << value << std::endl;
}
}
// Concept-based overloading
void handle(Integral auto value) {
std::cout << "Integral: " << value << std::endl;
}
void handle(std::floating_point auto value) {
std::cout << "Float: " << value << std::endl;
}
void handle(Container auto container) {
std::cout << "Container of size: " << container.size() << std::endl;
}
#include <type_traits>
// Type properties
static_assert(std::is_integral_v<int>);
static_assert(std::is_floating_point_v<double>);
static_assert(std::is_pointer_v<int*>);
static_assert(std::is_array_v<int[5]>);
static_assert(std::is_const_v<const int>);
// Type relationships
static_assert(std::is_same_v<int, int>);
static_assert(std::is_base_of_v<Base, Derived>);
static_assert(std::is_convertible_v<int, double>);
// Type modifications
using NoConst = std::remove_const_t<const int>; // int
using NoRef = std::remove_reference_t<int&>; // int
using NoPointer = std::remove_pointer_t<int*>; // int
using AddConst = std::add_const_t<int>; // const int
using AddPointer = std::add_pointer_t<int>; // int*
// Conditional types
using Type = std::conditional_t<true, int, double>; // int
// Check if type has size() method
template<typename T, typename = void>
struct has_size : std::false_type {};
template<typename T>
struct has_size<T, std::void_t<decltype(std::declval<T>().size())>>
: std::true_type {};
template<typename T>
inline constexpr bool has_size_v = has_size<T>::value;
// Usage
static_assert(has_size_v<std::vector<int>>);
static_assert(!has_size_v<int>);
// Check if type is iterable
template<typename T, typename = void>
struct is_iterable : std::false_type {};
template<typename T>
struct is_iterable<T, std::void_t<
decltype(std::declval<T>().begin()),
decltype(std::declval<T>().end())>>
: std::true_type {};
template<typename T>
inline constexpr bool is_iterable_v = is_iterable<T>::value;
// Factorial at compile time
template<int N>
struct Factorial {
static constexpr int value = N * Factorial<N - 1>::value;
};
template<>
struct Factorial<0> {
static constexpr int value = 1;
};
constexpr int fact5 = Factorial<5>::value; // 120
// Fibonacci at compile time
template<int N>
struct Fibonacci {
static constexpr int value = Fibonacci<N - 1>::value + Fibonacci<N - 2>::value;
};
template<>
struct Fibonacci<0> {
static constexpr int value = 0;
};
template<>
struct Fibonacci<1> {
static constexpr int value = 1;
};
constexpr int fib10 = Fibonacci<10>::value; // 55
// Type list definition
template<typename... Types>
struct TypeList {};
// Get size of type list
template<typename List>
struct Length;
template<typename... Types>
struct Length<TypeList<Types...>> {
static constexpr size_t value = sizeof...(Types);
};
// Get type at index
template<size_t Index, typename List>
struct At;
template<size_t Index, typename Head, typename... Tail>
struct At<Index, TypeList<Head, Tail...>>
: At<Index - 1, TypeList<Tail...>> {};
template<typename Head, typename... Tail>
struct At<0, TypeList<Head, Tail...>> {
using type = Head;
};
// Usage
using MyList = TypeList<int, double, char, std::string>;
static_assert(Length<MyList>::value == 4);
using SecondType = At<1, MyList>::type; // double
// Static polymorphism via CRTP
template<typename Derived>
class Base {
public:
void interface() {
static_cast<Derived*>(this)->implementation();
}
void common_functionality() {
std::cout << "Common code" << std::endl;
}
};
class Derived1 : public Base<Derived1> {
public:
void implementation() {
std::cout << "Derived1 implementation" << std::endl;
}
};
class Derived2 : public Base<Derived2> {
public:
void implementation() {
std::cout << "Derived2 implementation" << std::endl;
}
};
// Usage
template<typename T>
void use(Base<T>& obj) {
obj.interface(); // No virtual function overhead
}
Derived1 d1;
Derived2 d2;
use(d1); // Derived1 implementation
use(d2); // Derived2 implementation
// Expression template for lazy evaluation
template<typename E>
class VecExpression {
public:
double operator[](size_t i) const {
return static_cast<const E&>(*this)[i];
}
size_t size() const {
return static_cast<const E&>(*this).size();
}
};
class Vec : public VecExpression<Vec> {
std::vector<double> data;
public:
Vec(size_t n) : data(n) {}
double& operator[](size_t i) { return data[i]; }
double operator[](size_t i) const { return data[i]; }
size_t size() const { return data.size(); }
template<typename E>
Vec& operator=(const VecExpression<E>& expr) {
for (size_t i = 0; i < size(); ++i) {
data[i] = expr[i];
}
return *this;
}
};
// Addition expression
template<typename E1, typename E2>
class VecSum : public VecExpression<VecSum<E1, E2>> {
const E1& lhs;
const E2& rhs;
public:
VecSum(const E1& l, const E2& r) : lhs(l), rhs(r) {}
double operator[](size_t i) const {
return lhs[i] + rhs[i];
}
size_t size() const { return lhs.size(); }
};
// Operator overload
template<typename E1, typename E2>
VecSum<E1, E2> operator+(const VecExpression<E1>& lhs,
const VecExpression<E2>& rhs) {
return VecSum<E1, E2>(static_cast<const E1&>(lhs),
static_cast<const E2&>(rhs));
}
// Usage: single loop evaluation
Vec v1(1000), v2(1000), v3(1000), v4(1000);
v4 = v1 + v2 + v3; // Efficient: no temporary vectors
// Constexpr function (can be compile-time or runtime)
constexpr int square(int n) {
return n * n;
}
constexpr int value1 = square(5); // Compile-time
int x = 5;
int value2 = square(x); // Runtime
// Constexpr with complex logic (C++14+)
constexpr int fibonacci(int n) {
if (n <= 1) return n;
int a = 0, b = 1;
for (int i = 2; i <= n; ++i) {
int temp = a + b;
a = b;
b = temp;
}
return b;
}
// Constexpr with std::array
constexpr auto make_array() {
std::array<int, 5> arr{};
for (size_t i = 0; i < arr.size(); ++i) {
arr[i] = i * i;
}
return arr;
}
constexpr auto squares = make_array();
// Must be evaluated at compile-time
consteval int cube(int n) {
return n * n * n;
}
constexpr int value3 = cube(5); // OK: compile-time
// int y = 5;
// int value4 = cube(y); // ERROR: not compile-time
// is_constant_evaluated
constexpr int conditional_compute(int n) {
if (std::is_constant_evaluated()) {
// Compile-time path
return n * n;
} else {
// Runtime path (might use hardware instructions)
return n * n; // Could use intrinsics
}
}
// Print type at compile time (causes error with type info)
template<typename T>
struct DebugType;
// DebugType<decltype(value)> debug; // Error shows type
// Static assert for debugging
template<typename T>
void check_type(T value) {
static_assert(std::is_integral_v<T>, "T must be integral");
static_assert(sizeof(T) >= 4, "T must be at least 4 bytes");
}
// Concept for better error messages
template<typename T>
concept AtLeast4Bytes = sizeof(T) >= 4;
template<AtLeast4Bytes T>
void process(T value) {
// If T doesn't satisfy concept, clear error message
}
// Before C++20: cryptic errors
template<typename T>
void old_process(T value) {
value.size(); // Error if T doesn't have size()
}
// C++20: Clear concept-based errors
template<typename T>
concept HasSize = requires(T t) {
{ t.size() } -> std::convertible_to<std::size_t>;
};
template<HasSize T>
void new_process(T value) {
value.size(); // Clear error if T doesn't satisfy HasSize
}
// Static assert for early error
template<typename T>
void checked_process(T value) {
static_assert(HasSize<T>, "T must have size() method");
value.size();
}
Use this skill when:
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.