Monday, October 5, 2026

C++ template interview cheat sheet

 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.

No comments:

Post a Comment