Here’s a C++ template interview cheat sheet with each question followed by an interview-ready answer, explanation, and example.
1. What is a template in C++? Why do we use templates?
Answer:
A template allows us to write generic code that works with different data types without duplicating the implementation.
There are two main types:
* Function templates
* Class templates
Example
cpp
template <typename T>
T add(T a, T b)
{
return a + b;
}
Now the same function can work with multiple types:
cpp
add(10, 20); // int
add(2.5, 3.5); // double
add(std::string("A"), "B"); // string
The compiler generates the appropriate version when the template is instantiated.
Why use templates?
* Code reuse
* Type safety
* Compile-time polymorphism
* Generic programming
* Often zero runtime overhead
Interview point: Templates are primarily a mechanism for compile-time polymorphism, whereas virtual functions provide runtime polymorphism.
───
2. What's the difference between typename and class in templates?
For declaring a template type parameter, they are generally equivalent:
cpp
template <typename T>
class Box {};
and:
cpp
template <class T>
class Box {};
Both mean that T is a type.
But typename has another important use
Consider:
cpp
template <typename T>
void foo()
{
T::value_type x;
}
This is problematic because the compiler doesn't initially know whether T::value_type is a type or something else.
We tell the compiler explicitly:
cpp
template <typename T>
void foo()
{
typename T::value_type x;
}
Here, typename means:
T::value_type is a type.
Interview trap
Don't say "typename and class are always interchangeable."
They're interchangeable when declaring a template type parameter, but typename has additional meaning for dependent names.
───
3. What is template specialization?
Specialization allows us to provide a different implementation for a particular type or category of types.
There are two important forms.
Full specialization
cpp
template <typename T>
class Printer
{
public:
void print()
{
std::cout << "Generic\n";
}
};
For int, we can provide a completely different implementation:
cpp
template <>
class Printer<int>
{
public:
void print()
{
std::cout << "Integer\n";
}
};
Now:
cpp
Printer<double> p1;
p1.print(); // Generic
Printer<int> p2;
p2.print(); // Integer
Partial specialization
We can specialize a class template for a category of types.
cpp
template <typename T>
class Printer
{
};
For pointers:
cpp
template <typename T>
class Printer<T*>
{
};
Now:
cpp
Printer<int> p1; // primary template
Printer<int*> p2; // pointer specialization
Important interview question
Can function templates be partially specialized?
No.
Class templates can be partially specialized.
Function templates can instead be overloaded.
───
4. What's the difference between function template specialization and overloading?
Consider:
cpp
template <typename T>
void print(T value)
{
std::cout << "Template\n";
}
We can specialize it:
cpp
template <>
void print<int>(int value)
{
std::cout << "Specialization\n";
}
Or we can overload it:
cpp
void print(int value)
{
std::cout << "Overload\n";
}
These are not equivalent.
Why?
Overloading participates in overload resolution.
Template specialization happens after the appropriate template has been selected.
This can lead to surprising behavior, particularly when templates are called through other templates.
Interview recommendation
If asked:
"Should I specialize a function template or overload it?"
A good answer is:
Function templates generally cannot be partially specialized, and overloading is often preferable when customizing function behavior. Class template specialization is the normal mechanism for specialization.
───
5. What is SFINAE?
SFINAE stands for:
Substitution Failure Is Not An Error
It means that when substituting template arguments causes an invalid type or expression in the immediate context, that template can simply be removed from consideration rather than producing a compilation error.
A classic example:
cpp
template <typename T>
typename T::value_type getValue(T obj)
{
return obj[0];
}
Suppose:
cpp
std::vector<int> v;
getValue(v);
std::vector<int> has:
cpp
value_type
so the template works.
But:
cpp
int x;
getValue(x);
doesn't have int::value_type.
With SFINAE, we can use this fact to control which functions participate in overload resolution.
Common SFINAE tools
cpp
std::enable_if
std::void_t
std::is_same
std::is_integral
std::is_convertible
For example:
cpp
template <
typename T,
typename = std::enable_if_t<std::is_integral_v<T>>
>
void foo(T value)
{
std::cout << "Integral\n";
}
This function only participates when T is an integral type.
Modern C++
C++20 concepts provide a much cleaner solution:
cpp
template <std::integral T>
void foo(T value)
{
}
So an excellent interview answer is:
SFINAE was historically used to constrain templates. In modern C++, concepts are usually preferred because they're clearer and produce better diagnostics.
───
6. What are variadic templates?
A variadic template can accept zero or more template arguments.
cpp
template <typename... Args>
void print(Args... args)
{
}
Args... is called a parameter pack.
For example:
cpp
print(1, 2.5, "hello", 'A');
Args could represent:
text
int
double
const char*
char
Fold expressions
C++17 introduced fold expressions, making variadic templates much easier to use.
For example:
cpp
template <typename... Args>
auto sum(Args... args)
{
return (args + ...);
}
Then:
cpp
auto result = sum(1, 2, 3, 4);
Conceptually:
cpp
((1 + 2) + 3) + 4
Why are variadic templates useful?
They're heavily used in:
* std::tuple
* std::make_unique
* std::make_shared
* std::format
* Generic wrappers
* Perfect forwarding
───
7. What is template instantiation?
A template is essentially a blueprint. Instantiation happens when the compiler needs a concrete version of that template.
Example:
cpp
template <typename T>
T square(T x)
{
return x * x;
}
When we write:
cpp
square(5);
the compiler can instantiate:
cpp
int square(int x)
{
return x * x;
}
And:
cpp
square(2.5);
can result in:
cpp
double square(double x)
{
return x * x;
}
Three concepts worth knowing
Implicit instantiation
cpp
square(5);
The compiler generates what's needed automatically.
Explicit specialization
cpp
template <>
int square<int>(int x)
{
// special implementation
}
Explicit instantiation
cpp
template int square<int>(int);
This explicitly tells the compiler to instantiate the template for int.
Interview follow-up
Why are templates usually defined in header files?
Because the compiler generally needs to see the template definition at the point of instantiation.
This is why you'll commonly see:
cpp
// MyClass.h
template <typename T>
class MyClass
{
...
};
rather than putting the implementation only in a .cpp file.
───
8. What are dependent names, and why do we need typename?
This is one of the classic advanced template questions.
Consider:
cpp
template <typename T>
void foo()
{
T::value_type x;
}
The problem is that T is a dependent type. The compiler doesn't know what T will be yet.
Therefore, it doesn't know whether:
cpp
T::value_type
is a type or something else.
We tell the compiler:
cpp
template <typename T>
void foo()
{
typename T::value_type x;
}
The typename says:
Treat T::value_type as a type.
Another related keyword: template
You can encounter:
cpp
obj.template foo<int>();
The template keyword tells the compiler that foo should be interpreted as a template when obj depends on a template parameter.
These two keywords are frequently tested together in senior C++ interviews.
───
9. What are C++20 concepts?
Concepts allow us to specify requirements on template parameters.
Before C++20, you might write:
cpp
template <
typename T,
typename = std::enable_if_t<std::is_arithmetic_v<T>>
>
T add(T a, T b)
{
return a + b;
}
This works, but it's difficult to read.
With C++20:
cpp
template <typename T>
concept Numeric = std::is_arithmetic_v<T>;
template <Numeric T>
T add(T a, T b)
{
return a + b;
}
Or using a standard concept:
cpp
template <std::integral T>
T add(T a, T b)
{
return a + b;
}
Advantages of concepts
* More readable
* Better compiler errors
* Clearly communicates requirements
* Cleaner overload resolution
* Replaces many traditional SFINAE techniques
Interview answer
A good concise answer:
Concepts are named compile-time constraints on template parameters introduced in C++20. They make template requirements explicit and generally provide clearer diagnostics than SFINAE.
───
10. What is perfect forwarding, and how is it related to templates?
This is probably the most important advanced topic on this list.
Consider:
cpp
template <typename T>
void wrapper(T&& arg)
{
foo(std::forward<T>(arg));
}
Here T&& can be a forwarding reference when T is deduced.
It allows the wrapper to preserve whether the caller passed an lvalue or rvalue.
Example
cpp
void foo(const std::string& s)
{
std::cout << "lvalue\n";
}
void foo(std::string&& s)
{
std::cout << "rvalue\n";
}
Now:
cpp
std::string s = "hello";
wrapper(s); // lvalue
wrapper(std::string("hi")); // rvalue
std::forward<T> preserves that value category.
Why not just use std::move?
This is an important interview question.
std::moveunconditionally casts its argument to an rvalue.
std::forward<T> conditionally casts based on the original type/value category.
So:
cpp
std::move(x)
means roughly:
"Treat x as an rvalue."
Whereas:
cpp
std::forward<T>(x)
means:
"Preserve whether the caller originally gave me an lvalue or rvalue."
Reference collapsing
Perfect forwarding relies on reference collapsing rules:
Combination
Result
T& &
T&
T& &&
T&
T&& &
T&
T&& &&
T&&
This is very commonly asked in senior C++ interviews.
───
🔥 The 10 to memorize
If you want a compact interview revision list:
#
Question
Key concept
1
What are templates?
Generic/compile-time programming
2
typename vs class?
Template parameters + dependent types
3
What is specialization?
Full vs partial specialization
4
Specialization vs overloading?
Overload resolution
5
What is SFINAE?
Substitution failure
6
What are variadic templates?
Parameter packs/fold expressions
7
What is template instantiation?
Implicit/explicit instantiation
8
What are dependent names?
typename, template
9
What are concepts?
C++20 constraints
10
What is perfect forwarding?
Forwarding references/reference collapsing
For a senior C++ interview, I'd spend the most time on #5, #8, #9 and #10. Those are where interviewers can quickly move from basic template knowledge into deeper C++ understanding.