Type Aliases and Template Aliasing
A type alias is an alternative name for an existing type, not a new type.
One Line of Code, Many Systems
Programs are often written once and then compiled and run on different systems. A program that works on one system should ideally work on another without its source code being rewritten. This goal is called portability, and it is one of the main reasons programmers use type aliases.
Keep one question in mind as you read: if the same line of source code is built on two different implementations, can the text of that line stay exactly the same while the meaning of the type behind it changes? Type aliases are the feature that makes this possible, and the rest of this article traces how.
Why the Same Type Name Can Mean Different Types
The difficulty begins with types whose exact definition is not fixed. Some types are defined differently by different implementations. This means the same type name can refer to a different underlying type depending on where the program is built.
The source uses size_t as its example. The actual type named size_t is implementation-dependent. In one implementation it may be an unsigned int, while in another implementation the same name may refer to an unsigned long. A programmer reading the code sees the same name in both cases, but the underlying type behind that name is not the same everywhere.
The diagram shows the same written name resolving to different underlying types. Because the code only ever writes the alias, the source text stays identical across both implementations even though the types beneath it differ.
Where Portability Breaks Down
Suppose code uses an implementation-dependent type directly by its underlying name. That code is then tied to one particular implementation. When the program moves to a system where that underlying name refers to a different type, the code no longer describes the situation the author intended, and it must be edited by hand.
How an Alias Sits Between Name and Type
A type alias is an alternative name for an existing type, not a new type. Writing the alias is the same as writing the type it names, so the alias gives the programmer a convenient label without changing what the type is.
The important point is the direction of the relationship. The alias is the name the programmer writes. The underlying type is the existing type that the name stands for. The arrow points from the name to the type, not the other way around. The alias does not create a second type that happens to behave the same; it is simply another way of spelling the same type.
Tracing One Declaration Across Two Implementations
Here is the central benefit. If code uses an implementation-dependent type directly by its underlying name, that code is tied to one particular implementation. If code uses the alias instead, the alias can be defined to match whatever the current implementation uses. The code that names the alias keeps working without modification, because the programmer never wrote the underlying type name.
unsigned int count = 0;The declaration names the underlying type directly, so the line is tied to whatever unsigned int means on the one implementation the author had in mind.
size_t count = 0;The declaration names the alias. The same text keeps working on each implementation, because the alias is defined to match the implementation it is built on.
Tracing size_t Across Two Builds
The same source line, size_t count = 0;, is compiled on Implementation A and on Implementation B. What changes, and what stays the same?
- 1Read the source line
The text size_t count = 0; is identical in both builds. The programmer wrote only the alias, never the underlying type.
- 2Resolve the alias on Implementation A
On Implementation A, the name size_t refers to unsigned int, so count is an unsigned int in that build.
- 3Resolve the alias on Implementation B
On Implementation B, the same name refers to unsigned long, so count is an unsigned long in that build.
- 4Compare the two results
The source text did not change between the builds. Only the underlying type behind the name changed, which is exactly what the alias was designed to allow.
The source line stays identical, and the underlying type follows the implementation. The code moves without any rewriting.
Mistakes That Undo Portability
Common mistake Writing the underlying type directly instead of the alias
What it looks likeunsigned int count = 0; written where the code was meant to use size_t
Why it failsThe line now names one specific type and no longer follows the implementation, so the portability benefit is lost for that line.
Do this insteadWrite the alias so the source text does not name the underlying type.
Common mistake Assuming an alias always maps to one fixed width
What it looks likeBelieving size_t is always the same size as unsigned int on every system
Why it failsThe source states that the type is implementation-dependent, so the same name may refer to different underlying types on different implementations.
Do this insteadTreat the alias as a name whose meaning depends on the implementation, and check the definition on the target platform when the exact type matters.
Common mistake Treating the alias as a new, separate type
What it looks likeBelieving that writing size_t creates a distinct type unrelated to the type it names
Why it failsAn alias is an alternative name for an existing type, not a new type, so writing the alias is the same as writing the type it names.
Do this insteadRemember that the alias and the underlying type are the same type, seen through two names.
Common mistake Rewriting source code each time the program moves to another system, which defeats the purpose of the alias
Template Aliasing at a Glance
The topic also names template aliasing, which concerns alias templates: aliases that take template parameters. This article focuses on the plain alias, because the grounding for this lesson establishes the core idea: an alias is a name for an existing type, and it lets the source text avoid naming the underlying type.
Tracing an Alias Through a Function Parameter
A function declares its parameter as unsigned int instead of using the alias size_t. The same source is later built on an implementation where size_t refers to unsigned long. Predict what the declaration is tied to on that implementation, and explain how rewriting the declaration with the alias would prevent the problem.
Hints
- Ask which name in the declaration is the underlying type and which name the implementation controls.
- Think about what stays identical in the source text when the alias is used instead of the underlying name.
What do you think happens?
If the alias definition is changed for a new implementation, does code that uses the alias need to be edited?
Reveal answer
No. The code that names the alias keeps working without modification, because the programmer never wrote the underlying type name.
The alias can be defined to match whatever the current implementation uses, so the alias is the only place that has to change.
Key Takeaways
- A type alias is an alternative name for an existing type, not a new type, so writing the alias is the same as writing the type it names.
- Some types are implementation-dependent: the same name, such as size_t, may refer to unsigned int on one implementation and unsigned long on another.
- Code that uses the alias instead of the underlying type name can be written once and reused across implementations without modification.
- Writing the underlying type directly, or assuming a fixed meaning for an alias, weakens portability and reintroduces platform dependence.