What are templates in C++?
A template is a blueprint the compiler uses to generate a separate, fully typed function or class for each type you use it with, at compile time.
C++#include <iostream> #include <string> using namespace std; template <typename T> T maxOf(T a, T b) { return a > b ? a : b; } int main() { cout << maxOf(3, 7) << " " << maxOf(2.5, 1.5) << " " << maxOf<string>("pear", "apple") << "\n"; }This prints
7 2.5 pear. Without the explicit<string>, the arguments would be twoconst char*and>would compare addresses. See the templates docs.How do you write a class template? Give an example.
Put
template <typename T>before the class and useTwherever the type varies; eachStack<int>orStack<std::string>is a separate class.C++#include <iostream> #include <stdexcept> #include <string> #include <vector> using namespace std; template <typename T> class Stack { vector<T> items; public: void push(const T& x) { items.push_back(x); } T pop() { if (items.empty()) throw out_of_range("empty stack"); T top = items.back(); items.pop_back(); return top; } bool empty() const { return items.empty(); } }; int main() { Stack<string> s; s.push("a"); s.push("b"); cout << s.pop() << s.pop() << " " << s.empty() << "\n"; }This prints
ba 1(since C++17 the twos.pop()calls in one<<chain run left to right; see the evaluation order rules). Members are instantiated only when used.Which template does the compiler pick for
TypeName<int>,<double*>and<char>?C++#include <iostream> using namespace std; template <typename T> struct TypeName { static const char* get() { return "unknown"; } }; template <> struct TypeName<int> { static const char* get() { return "int"; } }; template <typename T> struct TypeName<T*> { static const char* get() { return "pointer"; } }; int main() { cout << TypeName<int>::get() << " " << TypeName<double*>::get() << " " << TypeName<char>::get() << "\n"; }It prints
int pointer unknown. The compiler picks the most specialized match:intuses the full specialization,double*the partial specialization forT*, andcharthe primary template.Only class and variable templates can be partially specialized; function templates are overloaded instead. Type traits such as
std::is_pointerare built this way.Why are templates usually defined in header files?
The compiler needs the full definition where the template is used, to generate code for that type. Defined only in
stack.cpp,Stack<int>::pushis never generated and the linker reports an undefined reference. Explicit instantiations in the.cppare the alternative, limiting users to those types.// stack.cpp template class Stack<int>; template class Stack<std::string>;What is SFINAE, and how do C++20 concepts replace it?
SFINAE ("substitution failure is not an error"): if substituting template arguments into a signature produces invalid code, that template is dropped from overload resolution instead of causing an error.
std::enable_ifuses it to switch overloads by type.C++#include <iostream> #include <type_traits> template <typename T> std::enable_if_t<std::is_integral_v<T>, const char*> kind(T) { return "integer"; } template <typename T> std::enable_if_t<std::is_floating_point_v<T>, const char*> kind(T) { return "floating"; } int main() { std::cout << kind(5) << " " << kind(2.0) << "\n"; }This prints
integer floating. C++20 concepts say the same directly, with readable errors.template <std::integral T> const char* kind(T) { return "integer"; } template <std::floating_point T> const char* kind(T) { return "floating"; }What are variadic templates and fold expressions?
A variadic template takes any number of arguments through a parameter pack (
typename... Args). C++17 fold expressions apply an operator across the pack without recursion.C++#include <iostream> template <typename... Args> auto sum(Args... args) { return (args + ...); } template <typename... Args> void printAll(const Args&... args) { ((std::cout << args << " "), ...); std::cout << "\n"; } int main() { std::cout << sum(1, 2, 3, 4) << "\n"; printAll(1, "two", 3.0); }This prints
10, then1 two 3(3.0 prints as3).sizeof...(args)gives the pack's size.std::make_uniqueandemplace_backuse variadic templates with perfect forwarding.What is the difference between templates and macros?
Macros are text substitution by the preprocessor; templates are part of the language and are type checked by the compiler. Macros also ignore scope and may evaluate an argument twice.
#define MAX(a, b) ((a) > (b) ? (a) : (b)) int i = 5; int m = MAX(i++, 3); // i++ runs twice: i ends at 7 template <typename T> T max2(T a, T b) { return a > b ? a : b; }Use templates or
constexprfunctions for code, and keep macros for include guards, conditional compilation and__FILE__/__LINE__in logging.What is the difference between
typenameandclassin a template?In a template parameter list there is none:
template <class T>andtemplate <typename T>mean the same thing.typenamehas a second job, though: inside a template it tells the compiler that a name depending on a template parameter is a type.C++#include <iostream> #include <vector> using namespace std; template <class Container> typename Container::value_type first(const Container& c) { typename Container::const_iterator it = c.begin(); // dependent type: typename required return *it; } int main() { vector<int> v = {4, 8, 15}; cout << first(v) << "\n"; }It prints
4. Withouttypename,Container::const_iteratoris parsed as a value and the code does not compile. C++20 drops the requirement in some places where only a type can appear, such as a function's return type.What are non-type template parameters?
A template parameter can be a compile-time value instead of a type: an integer, an enum, a pointer or a reference, plus floating-point values and some class types since C++20.
std::array<int, 3>uses one for its size.C++#include <array> #include <cstddef> #include <iostream> using namespace std; template <typename T, size_t N> size_t length(const T (&)[N]) { return N; } // N is deduced from the array type template <int Factor> int scale(int x) { return x * Factor; } int main() { int scores[] = {90, 75, 88, 62}; array<int, 3> fixed = {1, 2, 3}; cout << length(scores) << " " << fixed.size() << " " << scale<10>(3) << "\n"; }It prints
4 3 30. The value must be a constant expression, and each distinct value is a separate instantiation:std::array<int, 3>andstd::array<int, 4>are different types. Taking an array asconst T (&)[N]is the classic way to get its length; C++17 also allowstemplate <auto V>.What is CRTP (the curiously recurring template pattern)?
A class derives from a base template instantiated with itself (
struct Square : Shape<Square>). The base caststhisto the derived type and calls its functions, which gives polymorphism resolved at compile time: no vtable, and the calls can inline.C++#include <iostream> using namespace std; template <typename Derived> struct Shape { double area() const { return static_cast<const Derived*>(this)->areaImpl(); } void describe() const { cout << "area " << area() << "\n"; } }; struct Square : Shape<Square> { double side; explicit Square(double s) : side(s) {} double areaImpl() const { return side * side; } }; struct Rect : Shape<Rect> { double w, h; Rect(double w, double h) : w(w), h(h) {} double areaImpl() const { return w * h; } }; template <typename T> void print(const Shape<T>& s) { s.describe(); } int main() { print(Square(3)); print(Rect(2, 5)); }It prints
area 9andarea 10. The cost:Shape<Square>andShape<Rect>are unrelated types, so they cannot share one container. The standard library uses the pattern instd::enable_shared_from_this, and C++23's explicit object parameter (deducingthis) replaces many uses.
C++ Templates Interview Questions
Function and class templates, specialization, SFINAE, concepts and variadic templates.
10 questions