Skip to content

Templates and Generic Programming Interview Questions for C++

25 Templates and Generic Programming questions with answers for c++ roles — 6 easy, 13 medium, 6 hard.

About Templates and Generic Programming

Write code that works for any type using function and class templates. This topic covers specialization, variadic templates, fold expressions, type traits, SFINAE, C++20 concepts and compile-time computation with constexpr, along with practical concerns such as readable errors, code bloat and slow builds in template-heavy projects.

Sheet progressStart practicing
3 QUESTIONS FREESign up to unlock the full question bank and track your progress.Unlock every question and answer, then continue practising company-wise and package-wise.
3 questions free Unlock the rest in seconds
01

What are templates in C++? Explain function and class templates.

Save to ▾
Show answer
Templates let you write code once for many types; the compiler generates a concrete version for each type used. A function template such as template <typename T> T maxOf(T a, T b) works for int, double or std::string. A class template such as template <typename T> class Stack builds containers for any element type. The whole STL, including vector, map and algorithms, is built on templates.
02

What are non-type template parameters?

Save to ▾
Show answer
Template parameters can be values, not just types, as long as they are compile-time constants, such as integers, enums, pointers and, since C++20, some class types. std::array<int, 5> uses a size parameter. Example: template <int N> int power(int x) can be unrolled by the compiler. Each different value creates a separate instantiation, so they suit small fixed sets of values.
03

Write a generic function template that returns the larger of two values.

Save to ▾
Show answer
template <typename T> const T& maxOf(const T& a, const T& b) { return (a < b) ? b : a; } // usage int m = maxOf(3, 7); // T = int double d = maxOf(2.5, 1.5); // T = double auto s = maxOf<double>(3, 4.5); // explicit T avoids deduction conflict
04

Implement a generic Stack class template backed by std::vector.

Save to ▾
Show answer
#include <stdexcept> #include <vector> template <typename T> class Stack { std::vector<T> items_; public: void push(const T& x) { items_.push_back(x); } void push(T&& x) { items_.push_back(std::move(x)); } void pop() { if (items_.empty()) throw std::out_of_range("empty stack"); items_.pop_back(); } const T& top() const { return items_.back(); } bool empty() const { return items_.empty(); } std::size_t size() const { return items_.size(); } };
05

Compute a factorial at compile time.

Save to ▾
Show answer
constexpr unsigned long long factorial(unsigned n) { unsigned long long r = 1; for (unsigned i = 2; i <= n; ++i) r *= i; return r; } static_assert(factorial(5) == 120); constexpr auto f10 = factorial(10); // computed by the compiler // Pre-C++14 style used template recursion: // template <unsigned N> struct Fact { static const unsigned long long v = N * Fact<N - 1>::v; }; // template <> struct Fact<0> { static const unsigned long long v = 1; };
06

How do you keep your C++ knowledge up to date with new standards?

Save to ▾
Show answer
Situation: I noticed many tutorials still teach C++98 style. Task: learn modern practices properly. Action: I follow cppreference for each new standard, watch selected conference talks, read the C++ Core Guidelines and try features such as concepts, ranges and std::format in small practice projects compiled with recent GCC and Clang. Result: I can explain when a modern feature helps and when older code is fine.
07

Why are templates usually defined in header files?

Save to ▾
Show answer
A template is only a pattern; code is generated when it is instantiated with concrete types, and the compiler must see the full definition at that point. If the body lives in a .cpp file, other translation units cannot instantiate it and you get linker errors. The usual fix is defining templates in headers, or using explicit instantiation in the .cpp for a known, fixed set of types.
08

What is the difference between full and partial template specialization?

Save to ▾
Show answer
Full specialization provides a separate implementation for one exact set of template arguments, such as template <> class Hash<std::string>. Partial specialization, allowed only for class and variable templates, covers a family of arguments, such as template <typename T> class Hash<T*> for all pointer types. Function templates cannot be partially specialised; overloading is used instead.
09

What are C++20 concepts?

Save to ▾
Show answer
Concepts are named compile-time predicates on template parameters. You can write template <std::integral T> T gcd(T a, T b) or define your own with a requires expression. If a type does not satisfy the concept, the compiler reports a short, readable error at the call site instead of pages of instantiation errors. Concepts also allow overloading by constraint and document the template's expectations.
10

When do you need the typename keyword inside a template?

Save to ▾
Show answer
Inside a template, a name that depends on a template parameter, such as T::value_type, could be a type or a static member, so the compiler assumes it is a value. You must write typename T::value_type x; to say it is a type. Similarly, a dependent member template needs the template keyword, as in obj.template get<0>(). C++20 relaxes this in some contexts, but the rule still matters.
11

What are type traits and how does if constexpr use them?

Save to ▾
Show answer
Type traits in <type_traits> answer questions about types at compile time, such as std::is_integral_v<T>, std::is_pointer_v<T> or std::is_same_v<T, U>, and transform types, such as std::remove_reference_t. if constexpr picks a branch at compile time and discards the other, so code like if constexpr (std::is_integral_v<T>) can call integer-only operations safely inside a generic function.
12

What is template argument deduction and class template argument deduction?

Save to ▾
Show answer
For function templates the compiler deduces T from the call, so maxOf(3, 7) deduces int; mixing int and double fails because T would be ambiguous. Class template argument deduction, added in C++17, lets you write std::vector v{1, 2, 3}; or std::pair p(1, 2.5); without spelling the template arguments. Deduction guides can be written to tell the compiler how to deduce types from constructors.
13

A teammate complains that a template function produces hundreds of lines of compiler errors when misused. How do you improve this?

Save to ▾
Show answer
Constrain the template so misuse fails early with a clear message. With C++20 I would add a concept or requires clause, for example template <std::totally_ordered T>, so the error names the unmet requirement at the call site. On older standards, a static_assert with a readable message at the top of the function body helps. Good naming and a comment on expected type properties also help.
14

A generic average function must accept only numeric types. How would you enforce that?

Save to ▾
Show answer
In C++20 I would constrain it: template <typename T> requires std::is_arithmetic_v<T> double average(const std::vector<T>& v). Passing a vector of strings then fails with a clear constraint error. On C++17 the same check can go in a static_assert or std::enable_if. I would also decide whether bool and char should be allowed, since they are technically arithmetic types.
15

You need a container that holds ints, strings and doubles together. Which approach would you choose?

Save to ▾
Show answer
If the set of types is fixed and known, std::vector<std::variant<int, std::string, double>> is type-safe and needs no heap per element; std::visit handles each type. If types are open-ended, std::any works but needs any_cast and loses compile-time checks. If the items share behaviour, a base class interface with unique_ptr is cleanest. I usually prefer variant for closed sets.
16

A generic maxOf template gives wrong results when called with two C-style string literals. Why, and how do you fix it?

Save to ▾
Show answer
T is deduced as const char*, so the template compares pointer addresses instead of the characters. The result depends on where the literals are stored. Fix it by adding an overload for const char* that uses std::strcmp, or better, call it with std::string or std::string_view, where operator< compares contents. This shows why generic code must consider what operations mean for each type.
17

Write a variadic function that sums any number of arguments and one that prints them.

Save to ▾
Show answer
#include <iostream> template <typename... Args> auto sum(Args... args) { return (args + ...); // unary right fold } template <typename... Args> void printAll(const Args&... args) { ((std::cout << args << ' '), ...); // comma fold std::cout << '\n'; } // sum(1, 2, 3.5) returns 6.5; printAll(1, 'x', 2.5) prints 1 x 2.5
18

Write a C++20 concept and use it to constrain a function.

Save to ▾
Show answer
#include <concepts> #include <string> template <typename T> concept Printable = requires(T t) { { t.toString() } -> std::convertible_to<std::string>; }; template <Printable T> std::string describe(const T& obj) { return "Item: " + obj.toString(); } struct User { std::string name; std::string toString() const { return name; } }; // describe(User{"Asha"}) compiles; describe(42) fails with a clear message.
19

Tell me about a time you wrote generic, reusable code that saved effort for your team.

Save to ▾
Show answer
Situation: three services each had their own copy of retry logic for network calls. Task: remove duplication without slowing them down. Action: I wrote a small header-only template, retry with a callable and a policy for attempts and backoff, added unit tests and documented examples. Result: all three services adopted it, around 600 lines of duplicate code were deleted and a bug fix now happens in one place.
20

What are variadic templates and fold expressions?

Save to ▾
Show answer
A variadic template accepts any number of template arguments using a parameter pack, written template <typename... Args>. Before C++17 packs were processed recursively. Fold expressions from C++17 apply an operator across the whole pack in one line, for example return (args + ...); sums all arguments. They power std::make_unique, std::tuple, std::format and logging functions that take arbitrary arguments.
21
Save to ▾
Show answer
Substitution Failure Is Not An Error: when the compiler substitutes template arguments and the resulting declaration is invalid, that candidate is silently removed from overload resolution instead of causing an error. It was traditionally used with std::enable_if to enable functions only for certain types, such as integral types. In C++20, concepts and requires clauses replace most SFINAE tricks with clearer syntax and error messages.
22

The release binary has grown very large and analysis shows many template instantiations. What can you do?

Save to ▾
Show answer
Each distinct set of template arguments generates separate code, so heavy generic code bloats binaries. I would find the biggest symbols with tools like bloaty or nm, move type-independent logic into a non-template base or helper, use type erasure for rarely hot paths, limit instantiations with extern template, and enable link-time optimisation plus identical code folding to merge duplicate functions.
23

Build times have become very slow because heavy templates are included everywhere. How do you speed them up?

Save to ▾
Show answer
I would measure first with -ftime-trace or build analyzers to find the costly headers. Then reduce includes with forward declarations, move template-heavy implementation details behind non-template interfaces, use extern template with explicit instantiation for common types, enable precompiled headers and a compiler cache such as ccache, and evaluate C++20 modules where the toolchain supports them well.
24

How do you decide between templates and virtual functions for polymorphism?

Save to ▾
Show answer
Templates give static polymorphism: resolved at compile time, inlinable and fast, but types must be known at compile time and code size grows. Virtual functions give dynamic polymorphism: one compiled body, types can be chosen at run time, plugins are possible, at the cost of an indirect call. I use templates for performance-critical generic algorithms and virtual interfaces for runtime-configurable components.
25

Implement your own is_pointer type trait.

Save to ▾
Show answer
template <typename T> struct IsPointer { static constexpr bool value = false; }; template <typename T> struct IsPointer<T*> { // partial specialization for pointers static constexpr bool value = true; }; template <typename T> inline constexpr bool IsPointer_v = IsPointer<T>::value; static_assert(IsPointer_v<int*>); static_assert(!IsPointer_v<int>); // The real std::is_pointer also strips const and volatile first.

Frequently asked questions

How important is Templates and Generic Programming in C++ interviews?

Write code that works for any type using function and class templates. This topic covers specialization, variadic templates, fold expressions, type traits, SFINAE, C++20 concepts and compile-time computation with constexpr, along with practical concerns such as readable errors, code bloat and slow builds in template-heavy projects.

How should I use the Templates and Generic Programming sheet?

Go top to bottom — easy to hard. Answer before opening each answer, tick what you solved and save misses to Last-Minute Revision.