5.2.15 · D1C++ Programming

Foundations — Template specialization — full and partial

1,817 words8 min readBack to topic

Before you can read template<class T> struct Box<T*> and know what it means, you must be able to read every piece: what template does, what the angle brackets <...> hold, what class T versus <T*> versus <> each say. This page builds all of them from nothing, in the order they stack.


1 — What is a type?

The picture: think of memory as a long strip of boxes. A type is a stencil laid over the strip that says "these 4 boxes together are one int; read them this way."

Figure — Template specialization — full and partial

Why the topic needs it: specialization is entirely about which type you are overriding for. If you don't crisply see int, int*, and pair<A,B> as different types with different shapes, the whole page is fog.


2 — The angle brackets <...> and what "generic" means

Compare two lines you already half-know:

  • max(3, 5) — round brackets pass values 3 and 5.
  • Box<int> — angle brackets pass a type int.

Why the topic needs it: full specialization writes template<> (no blanks left) and partial writes template<class T> ... <T*> (one blank still open, but constrained in shape). You cannot tell those apart until "blank" (parameter) and "filled-in value" (argument) are separate ideas in your head.


3 — template<class T> : declaring the recipe

The picture: template<class T> is a cookie-cutter machine. Feed it int → it stamps out the int version. Feed it double → the double version. One machine, unlimited cookies.

Figure — Template specialization — full and partial

Why the topic needs it: the primary template in the parent (template<class T> struct TypeName) is exactly this machine. Every specialization is defined relative to it.


4 — Instantiation: when the recipe becomes real code

The picture: the recipe sits in a cookbook doing nothing. The first time you order Box<int>, the kitchen actually cooks it. That "first cook" is the instantiation.

Why the topic needs it: the entire "selection rule" on the parent page fires at instantiation time — that is when the compiler decides which recipe (primary / full / partial) to run.


5 — The pointer star * and "shape" of a type

Figure — Template specialization — full and partial

Why the topic needs it: partial specialization = matching on shape, not on exact identity. Without a mental image of int* as "a wrapper around int," the pattern TypeName<T*> is meaningless.


6 — struct { ... }, static, and ::

The picture: Box<int> is a labelled drawer. static members are printed on the drawer's front, readable without opening it. :: is your finger pointing at that label.

Why the topic needs it: every worked example calls Printer<bool>::fmt() or IsPtr<int*>::value. The :: is how you ask the specialized recipe what it produced.


7 — template<> : the "no blanks left" marker

Read it as a countdown of blanks:

You write Blanks remaining Meaning
template<class T> struct Box 1 (T) primary recipe
template<class T> struct Box<T*> 1 (T), but shape-locked to pointer partial spec
template<> struct Box<int> 0 full spec for exactly int

Why the topic needs it: this table is the "three things to distinguish" from the parent, but now every symbol in it is earned. Forgetting template<> (parent trap #1) makes the compiler think you're redeclaring the primary — which now makes sense, because with no template<> marker there's no signal "override incoming."


8 — "More specialized" = smaller set of matching types

Figure — Template specialization — full and partial

Why the topic needs it: the parent's "partial ordering" and the ambiguity error are pure set-logic. Two patterns are ambiguous exactly when neither circle sits inside the other — they overlap without nesting. Now that word "ambiguous" is a picture, not a rule to memorize.


Prerequisite map

Type: int double bool

Angle brackets and arguments

Pointer star and shape

template of class T recipe

Instantiation at first use

Partial spec matches shape

template empty means full spec

Selection rule at instantiate time

Sets of types and subset

Template Specialization full and partial

See it in action on the parent: Template specialization — full and partial (index 5.2.15). The natural next stops are Templates — function and class basics (the recipe machine itself), Type Traits and std::is_pointer (partial spec turned into a tool), and Overload Resolution vs Specialization (why functions can't be partially specialized).


Equipment checklist

A type tells the compiler two things — which?
How big a value is (bytes) and what operations are allowed on it.
Difference between a template parameter and a template argument?
Parameter = the blank named in the recipe (T); argument = the concrete type dropped in (int).
Does class in template<class T> force T to be a class?
No — it just means "type parameter"; typename T is identical and T can be int, a pointer, anything.
What is instantiation and when does it happen?
The compiler stamping the recipe into real code for a specific type, triggered at the type's first use.
What does the type int* mean, and how is it a "shape"?
"Address where an int lives" — a pointer wrapper around int; the shape is "pointer-to-something".
What does the :: scope operator do in Printer<bool>::fmt()?
Reaches inside the type Printer<bool> to grab its member fmt.
What does template<> (empty brackets) signal?
Zero blanks remain — this is a FULL specialization for exact types.
In set terms, what does "more specialized" mean?
The pattern claims a SMALLER set of types (a subset), so the compiler prefers it.
When are two partial specializations ambiguous, pictured as sets?
When their type-sets overlap but neither is a subset of the other — no nesting.
Why must a specialization appear before the type's first use?
Because the generic recipe gets cooked at first instantiation; a later override arrives too late.