Template Design Principles
Templates are used to express algorithms that apply to many argument types.
One Logic, Many Kinds of Data
Many programs need the same logic over and over again, but applied to different kinds of data. A sorting routine is a good example: the steps for putting values into order are the same whether the values are numbers, words, or records of some custom kind. A stack of items and a list of values follow the same pattern. Templates are the tool for describing code this way, so that the logic is written once and then used with many types.
What do you think happens?
You have written a sorting routine that works on a list of integers. What has to change in the routine itself so that it can sort a list of text strings instead?
Reveal answer
Only the type of the data needs to be supplied; the written steps can stay the same
The source describes the key idea as separation. The steps of the algorithm are written in terms of the operation being performed, while the specific type of the data is left open. When a particular argument type is needed, that type is supplied and the same written logic serves it.
Templates as Patterns with Open Type Slots
A template is a pattern with open type slots. The pattern describes the structure of an algorithm or a container, and the concrete types that fill those slots are chosen later, when the template is used.
Think of a template as a fixed body of logic with a blank in it. The blank is the type parameter. Everything that does not depend on the type stays exactly as written. When the template is needed for a particular argument type, that type is supplied, and the compiler or language machinery produces a concrete version that uses it. The source states the purpose directly: use templates to express algorithms that apply to many argument types. The written logic is shared; the concrete versions differ only in the type that was plugged into the open slot.
Tracing One Template Through Two Argument Types
Applying a largest-value template to two types
A template describes an algorithm that returns the largest of three values. The steps are: start with the first value as the current largest; compare each remaining value with the current largest; replace the current largest when a bigger value appears. The type of the values is left open. Trace how the same written logic serves integers and text.
- 1Identify the open slot
The element type is the open slot. The steps mention only the operation of comparison and never name a specific type, so the logic is the same for any type that supports comparison.
- 2Supply integers
With the slot filled by integers and the values 4, 9, and 2, the steps run: current largest is 4; 9 is bigger, so it becomes 9; 2 is not bigger, so 9 stays. The result is 9.
- 3Supply text
With the slot filled by text and the values pear, apple, and plum, the same steps run: current largest is pear; apple is not bigger; plum is bigger than pear in alphabetical order, so the result is plum.
- 4Compare the two runs
The written steps did not change between the two runs. Only the type supplied for the slot changed, and the comparison operation carried the meaning of bigger for each type.
One written algorithm produced correct results for two different argument types, because only the type slot was filled differently each time.
Containers That Hold Any Element Type
Without templates, a container for integers and a container for text would each need its own separate definition, even though their structure is the same. Both hold a sequence of elements, store them in order, and offer the same ways of adding and reading elements. Only the element type differs. Expressing the container as a template keeps the shared structure in one place and leaves the element type to be chosen by whoever uses the container.
The diagram shows why the template form helps. Both containers have the same three ordered positions. Their structure is the shared part that the template keeps in one place. The stored values are the part that changes with the element type, and that part is supplied by the user of the container. A user-defined type can be stored in the same way, because the container does not need to know what the element is in order to hold it.
Raising the Level of Abstraction
Abstraction means working with the idea of something rather than its every concrete detail. Templates raise the level of abstraction of code. The code is written in terms of general roles such as element, operation, or container, and concrete types are attached later. Because of this, a reader can understand what an algorithm or container does without tracing every specific type it might be used with.
When you write a template, name the roles in the code after what they do, such as element, operation, or container, rather than after a particular type. Readers can then follow the logic without needing to know which types will eventually use it.
Mistakes When Reading Templates
Common mistake Treating the template as one ordinary function that works for everything
Why it failsA template is a pattern. It becomes a concrete version only when a type is supplied for its open slot, so the concrete versions are what actually run.
Do this insteadThink of the template as the shared description and reason about each concrete version separately when you need exact behavior.
Common mistake Assuming the same steps are safe for any type without checking
Why it failsThe algorithm is written in terms of an operation, such as comparison. A supplied type must support the operation the steps rely on.
Do this insteadCheck that the chosen type supports every operation the template's steps use before relying on the result.
Common mistake Writing a separate container definition for each element type
Why it failsThe structure of the container is the same for integers, text, and other types, so repeating it duplicates the shared part.
Do this insteadExpress the container once as a template and let each user choose the element type.
Practice Reading a Template
A template describes a stack that holds items of an open element type, with operations to push an item and pop an item. Explain which part of this description stays the same for every use, and which part is chosen when the stack is used for a particular type.
Hints
- Ask which parts of the stack's behavior, such as push and pop, depend on the kind of item being stored.
- The element type is the open slot; the operations and the ordering of items are the shared structure.
Key Takeaways
- A template expresses an algorithm once, leaving the argument type open so the same written logic can serve many types.
- A template for a container keeps the shared structure in one place and lets the user of the container choose the element type.
- Templates raise the level of abstraction by describing code in terms of general roles such as element, operation, or container, with concrete types attached later.
- A template is a pattern; each concrete version exists only once a type has been supplied for the open slot.