Templates in C++: Reusable Parameterized Code with Worked Examples
Learn how one C++ template produces type-specific functions and classes. Follow exact calls, calculations, deduction failures, and practical corrections.
KnowledgeGate Team
Exam prep & CS education

Writing larger(int, int) and larger(double, double) repeats one comparison under two type names. A function template replaces the duplicates with one parameterised definition, but the compiler still has to select one T, validate operator>, and form a concrete specialisation. Non-type parameters and a broader runnable survey belong in Templates in C++: Function and Class Templates with Runnable Examples. Deduction, explicit arguments, body requirements and definition visibility are four separate failure points in this smaller trace.
C++ template parameters remove duplicated type-specific bodies
Without a template, the two functions may begin like this:
int larger(int a, int b) { return (a > b) ? a : b; }
double larger(double a, double b) { return (a > b) ? a : b; }Only the type changes. The comparison and selection algorithm stay the same. Copying it again for long creates another body to maintain and another place where an inconsistent edit can appear.
A template is a pattern parameterised by a type or value. In the example below, T is the template parameter, while int is one possible template argument. Instantiation forms a usable specialisation for an argument. Specialisation can mean that resulting type-specific form or an explicitly customised case. Templates operate at compile time. They are not runtime dynamic dispatch.
Review functions, references and class basics first in the C++ Tutorial: The Complete Learning Path from First Program to STL. Those foundations make it easier to read T as a compile-time type parameter rather than a runtime variable.
C++ function templates: read the type contract token by token
template <typename T>
T larger(T a, T b) {
return (a > b) ? a : b;
}template <...> introduces the template-parameter list. typename T declares T as a type parameter. The return type is T, and both function parameters are also T, so one chosen type must satisfy all three positions. In this body, values of that type must support operator> because the conditional expression compares a and b.
The equivalent spelling template <class T> declares the same kind of type parameter. typename is used here because it states the role of T directly.
The declaration does not promise that every imaginable type will work. It does not erase types at runtime, and it does not automatically make unrelated argument types compatible. For a chosen T, the comparison must be a valid expression, and the return statement must produce a value compatible with T. The compiler checks those requirements when the corresponding specialisation is needed.
C++ template deduction: trace successful and conflicting calls

Trace each call from its arguments to the selected T, then evaluate the comparison:
int first = larger(14, 9);
double second = larger(3.25, 7.50);
int third = larger<int>(6, 11);
double fourth = larger<double>(4, 6.5);Call | How | Comparison | Result |
|---|---|---|---|
| Deduced as |
|
|
| Deduced as |
|
|
| Explicitly |
|
|
| Explicitly |
|
|
Now consider larger(4, 6.5). The first argument suggests T = int, while the second suggests T = double. Deduction cannot select one T, so the call fails at compile time. The compiler does not silently choose the wider type during template argument deduction.
Make the argument types agree with larger(4.0, 6.5), which deduces double, or state the argument explicitly with larger<double>(4, 6.5). In the second repair, normal conversion changes 4 to 4.0 after T is fixed as double.

C++ class templates: one parameter creates distinct object types
A class template makes T part of each object's type. For C++20 constraints, bound invariants and clamp behaviour, use the C++ Function and Class Templates: Build One Type-Safe Range Pattern. Measurement<T> instead exposes unconstrained class instantiation and member-expression validity with the smallest useful state.
template <typename T>
class Measurement {
T value;
public:
explicit Measurement(T initial) : value(initial) {}
T shifted(T delta) const { return value + delta; }
};
Measurement<int> count(18);
Measurement<double> reading(21.25);count is a Measurement<int>. Its call count.shifted(4) calculates 18 + 4 = 22. reading is a Measurement<double>, and reading.shifted(0.75) calculates 21.25 + 0.75 = 22.0.
Measurement<int> and Measurement<double> are distinct instantiated types even though one source template defines both. The constructor and shifted() parameter use the same chosen T for each object.
The member body adds a requirement that deduction alone cannot prove: T + T must be valid, and its result must convert back to T. A type can therefore be deduced successfully and still fail when the compiler instantiates shifted().
C++ template instantiation and specialisation solve different jobs
Calling larger(14, 9) requires the compiler to form the int version. Calling larger(3.25, 7.50) similarly requires the double version. This is implicit instantiation. It does not follow that every use must enlarge the final binary, since compiler and linker optimisation may merge or remove code.
Mechanism | Purpose |
|---|---|
Primary template | Supplies the general parameterised pattern |
Normal overload | Supplies another signature or behaviour and participates in overload resolution |
Explicit specialisation | Customises the template for one exact argument set and starts with |
An explicit function-template specialisation declaration starts with template <>:
template <> const char* larger<const char*>(const char* a, const char* b);Raw C strings need a content-aware comparison policy. Applying ordinary > to pointers would compare addresses, not the character sequences they represent.
C++ template errors: identify the phase before changing code
Use each error to identify the missing rule:
larger(4, 6.5)-> conflicting deductions -> make both arguments the same type or specifydouble.Assuming any type works -> invalid
>or+expression -> check every operation used in the template body for the proposed type.Definition kept only in a separately compiled
.cppfile -> another translation unit cannot instantiate it -> normally keep the full template definition in a header, unless the program follows a deliberate explicit-instantiation design.Treating
Measurement<int>andMeasurement<double>as the same type -> conversion errors -> remember that they are distinct types, and provide code that permits any required conversion.Calling templates runtime polymorphism -> wrong execution model -> separate compile-time instantiation from virtual dispatch at runtime.
One more code-reading check helps. larger('b', 'a') deduces T = char. Both operands have the same type, the built-in comparison is valid, and 'b' > 'a' is true, so the function returns 'b'. This result concerns individual character values. It does not establish content-comparison behaviour for strings or raw C-string pointers.
C++ template questions: predict types before outputs
Exam-style and interview-style questions ask you to identify parameters and arguments, determine a deduced type, predict output, detect deduction conflicts, distinguish function and class templates, choose general or specialised behaviour, and test whether body operations are valid.
These checkpoints test type deduction, output prediction, and deduction conflicts:
larger(8, 12)deducesT = int;8 > 12is false, so the result is12.larger(2.5, 1.25)deducesT = double;2.5 > 1.25is true, so the result is2.5.larger(8, 12.0)fails deduction because the arguments suggestintanddouble. Make them agree or provide an explicit template argument.
Answer the three checkpoints before compiling. For exercises across more languages and placement-coding topics, continue with Coding & Skill Development Courses.
C++ templates: the short version
Find duplicated logic where only a type varies, replace that type with T, and confirm that every expression in the body works for the chosen T. Trace type deduction before tracing output. In particular, larger(4, 6.5) is a deduction problem, not a numeric-comparison problem.
Retype larger, predict all four successful results without compiling, then add the invalid mixed-type call and repair it both ways. For a structured sequence of concepts, MCQs and coding practice, continue with the C++ Programming Course.
Keep learning
Friend Functions in C++: Controlled Class Access with a Worked Example
See how a non-member friend function can validate and update two Wallet objects while private balances stay hidden from ordinary callers. Includes runnable C++ and an exact trace.
Data Types in C++: Fundamental and Derived Types with Worked Examples
Learn how C++ fundamental types differ from arrays, pointers, references, and function types. Trace one complete program, then test the conversion traps.
C++ Constructors and Object Initialization: Techniques, Order and a Worked Trace
Learn how C++ chooses default, parameterised, delegating and copy constructors, then trace member states and initialization order through complete code.
Virtual Functions MCQs: 11 Solved C++ Runtime Polymorphism Questions
Test C++ virtual dispatch with 11 solved exam MCQs, worked explanations and three code traces covering final overriders and safe base-class destruction.





