5.2.14 · D5C++ Programming

Question bank — Templates — function templates, class templates

1,583 words7 min readBack to topic

True or false — justify

These test whether you actually believe the definitions, or just memorised the words.

A template is itself a function or class you can call directly.
False. A template is a blueprint; nothing runnable exists until type deduction picks a concrete type and the compiler instantiates it. Calling maximum without arguments to deduce T compiles nothing.
template<class T> allows only class types, while template<typename T> allows any type.
False. For a type parameter they are 100% interchangeable; class here does NOT mean "only classes." typename was added purely to read better (and later gained a separate disambiguation job for dependent types).
An unused template still bloats your binary with machine code.
False. Code is generated only for the instantiations you actually use; an unused template produces zero machine code — that is why templates cost nothing you don't ask for.
Templates have a runtime cost compared to hand-writing a function per type.
False. The generated code is equivalent to hand-written type-specific code, so runtime overhead is zero — the work happens entirely at compile time.
Box<int> and Box<double> share the same class and just store different values.
False. They are completely different types, each independently instantiated; they share no code and are not interchangeable — a Box<int>* cannot point at a Box<double>.
A non-type template parameter like int N can be a variable read from user input.
False. Non-type parameters must be compile-time constants (that's the whole point — T data[N] needs N known when the code is compiled), so a runtime value is rejected.
Full specialization template<> changes the behaviour of the primary template for all types.
False. It provides a separate implementation for one specific type only; every other type still uses the generic version. The compiler picks the most specialized match.
Templates and macros are basically the same feature with nicer syntax.
False. Macros are text substitution with no type checking and double-evaluation bugs; templates are fully type-checked, respect scope, and generate real typed code.

Spot the error

Each line has one mistake rooted in a template rule. Name the rule.

maximum(3, 2.5); on template<typename T> T maximum(T,T).
T is deduced as int from 3 and double from 2.5conflicting deductions, one T cannot be both. Fix: maximum<double>(3, 2.5) or use two type parameters.
Putting the full template definition in template.cpp and only a declaration in the header.
The body is invisible to other translation units that try to instantiate it → linker error: undefined reference. Templates must be defined in the header so the whole body is seen at every point of use.
Defining a class-template member outside the class as T Box::get() const { ... }.
Missing the template head and the <T> qualifier — it must be template<typename T> then T Box<T>::get(), because the out-of-class definition is itself a template and Box<T> names the specific template class.
Writing Box b(42); (pre-C++17) expecting T to be deduced from the int.
Class templates cannot deduce their type from the constructor before C++17, so you must write Box<int> b(42);. (Function templates deduce; class templates historically do not.)
template<> void print(bool b){...} as a free-standing specialization while forgetting the primary template.
A specialization only makes sense against an existing primary template; template<> says "here is the override for one type," so the generic template<typename T> ... print must exist first for the compiler to specialize.
Using #define MAX(a,b) ((a>b)?(a):(b)) then calling MAX(i++, j).
Macro double-evaluation — i++ may run twice because it's text-pasted into the expression twice. A function template evaluates each argument exactly once. See Macros vs Templates.

Why questions

The "so what" behind each rule. Answer with a mechanism, not a slogan.

Why does a function template deduce T but a class template (pre-C++17) does not?
A function call provides argument types the compiler reads to infer T; a class name like Box appears with no arguments to deduce from (the constructor runs after the type is fixed), so you must state Box<int> yourself.
Why must the compiler see the whole body, not just a signature, to instantiate a template?
Instantiation literally generates the code of the body for the concrete type; a signature alone tells it the interface but gives it nothing to stamp out, so it cannot produce the machine code.
Why do templates keep type safety where void* + casts lose it?
void* erases the type so the compiler can't catch mixing an int* with a double*; a template keeps T as a real type through the whole body, so every operation is checked against that concrete type.
Why is a non-type parameter N powerful for arrays?
Because N is a compile-time constant, T data[N] lives on the stack with a size baked in — no heap allocation, and the size is available for compile-time checks and inlining.
Why does specialization exist if templates are meant to be "one size fits all"?
The generic code can be wrong for one type (e.g. printing a bool as 1/0 instead of true/false); specialization lets you override just that case while keeping the generic version for everything else.
Why are templates central to the STL and to Generic Programming generally?
They let one implementation work for any type that supports the needed operations (like vector<T> for any T), which is exactly the goal of generic programming: write the algorithm once, reuse for all types.
Why does maximum need T to support operator> but never mentions it?
The body uses a > b; the requirement is implicit in what the code does. Instantiation only fails (with an error) if you use a T that has no >, at the point of use — not at definition.

Edge cases

The boundaries the topic invites you to forget.

What happens if you instantiate maximum with a type that has no operator>, e.g. a struct?
Compilation fails at the point of instantiation with an error about the missing > — the template definition itself was fine, the error appears only when a bad T forces the body to be generated.
Does an entirely unused function template ever appear in the final binary?
No. With no instantiation there is nothing to generate, so it contributes zero machine code — it's as if you never wrote it.
Can two source files each instantiate Box<int> without a multiple-definition linker error?
Yes. Template instantiations are treated as inline/weak symbols, so the linker merges the identical copies rather than complaining — this is precisely why header definitions are safe.
What does template<typename T = int> class C {}; let you write, and why is C<> needed?
The default lets you omit the type: C<> means C<int>. The empty angle brackets are still required so the compiler knows C is being used as a template, not as a plain class.
If both a generic Printer<T> and a Printer<bool> specialization exist, which does Printer<bool> use?
The most specialized match, so the bool specialization wins; every other type falls back to the generic template.
Is Array<double, 5> the same type as Array<double, 6>?
No — the non-type parameter N is part of the type, so different N values give distinct, incompatible types (just like different T values do).
Can T in template<typename T, int N> be deduced while N is given explicitly, in a function template?
Yes — a function template can deduce the type parameters from arguments while non-type parameters like N are supplied explicitly or deduced from array sizes; only class templates (pre-C++17) refuse constructor deduction.

Recall One-line self-test before you move on

Cover the answers and explain, in your own words: (1) when code is generated, (2) where the definition must live, (3) why Box<int>Box<double>. If any answer is a bare "because that's the rule," reread the parent note.