Variadic Templates
Master variadic templates to create functions and classes that accept any number of arguments with full type safety
Learn variadic templates - the powerful C++11 feature that enables type-safe functions accepting any number of arguments of any types.
A Simple Example
#include <iostream>
// Base case: stop recursion
void print() {
std::cout << "\n";
}
// Variadic template: handles any number of arguments
template <typename T, typename... Args>
void print(T first, Args... rest) {
std::cout << first << " ";
print(rest...); // Recursive call with remaining arguments
}
int main() {
print(1, 2, 3); // 1 2 3
print("Hello", 42, 3.14, "World"); // Hello 42 3.14 World
print("Single"); // Single
return 0;
}
Breaking It Down
Parameter Packs typename... Args
-
Syntax:
typename... Argsdeclares a template parameter pack -
Usage:
Args... argsdeclares a function parameter pack - Represents zero or more template arguments of any types
-
Remember: The
...goes aftertypenamefor the type, before the name for expansion
Pack Expansion args...
-
Syntax:
args...expands the parameter pack -
Example:
print(rest...)expands toprint(arg1, arg2, arg3...) -
Works with expressions:
func(process(args)...)appliesprocessto each argument -
Remember: The
...goes after the pack name for expansion
Recursive Template Pattern
- Pattern: Peel off first argument, recurse with remaining arguments
- Base case: Function with no parameters or single parameter
- Each recursion: Compiler instantiates a new function template
- Remember: Without a base case, you get infinite recursion and compilation error
sizeof...(args) Operator
- What it does: Returns number of arguments in parameter pack at compile time
-
Usage:
sizeof...(Args)orsizeof...(args) - Returns: Compile-time constant - no runtime overhead
-
Remember: Different from
sizeof()which returns byte size
Why This Matters
- Variadic templates power essential modern C++ features you use every day.
- They enable std::tuple, std::bind, std::thread constructors, std::make_unique, and perfect forwarding.
- Understanding them opens the door to creating flexible, type-safe APIs that feel natural to use.
- They replace dangerous old-style variadic functions like printf with compile-time type checking.
Critical Insight
Variadic templates do not create loops at runtime - they generate multiple function instantiations at compile time. When you call print(1, 2, 3), the compiler generates three functions: one for (int, int, int), one for (int, int), and one for (int), plus the base case.
It is like unrolling a loop at compile time. The compiler does all the work ahead of time, generating optimized code for each specific case. By runtime, everything is already specialized and optimized - zero overhead!
Best Practices
Always provide a base case for recursive variadic templates: Without it, you get compilation errors from infinite recursion.
Use sizeof...(args) to query parameter pack size: This is a compile-time constant with zero runtime cost.
Combine with perfect forwarding: Use Args&&... args with std::forward<Args>(args)... for efficient argument passing.
Consider fold expressions (C++17): For simple operations, fold expressions are cleaner than recursion.
Common Mistakes
Forgetting the base case: Recursive variadic templates need a base case or you get infinite recursion at compile time.
Pack expansion syntax confusion: Use args... not ...args for pack expansion.
Assuming runtime loops: Variadic templates create multiple functions at compile time, not runtime loops.
Forgetting perfect forwarding: Use Args&&... and std::forward<Args>(args)... to avoid unnecessary copies.
Debug Challenge
This variadic template is missing the base case. Click the highlighted line to see what needs to be added:
Quick Quiz
- What does sizeof...(args) return?
- When are variadic template functions instantiated?
- What happens if you forget the base case in recursive variadic templates?
Practice Playground
Time to try out what you just learned! Play with the example code below, experiment by making changes and running the code to deepen your understanding.
Output:
Error:
Lesson Progress
- Fix This Code
- Quick Quiz
- Practice Playground - run once