Understanding Type Aliases
A type alias is an alternative name for an existing type, not a new type.
Writing Code Once, Running It Twice
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. To see why, we first need to look at a type whose exact definition is not fixed.
What do you think happens?
A programmer writes the name size_t in the same source file and compiles it on two different implementations. Do both builds necessarily use the same underlying type for that name?
Reveal answer
No, the same name can refer to different underlying types depending on the implementation.
Some types are implementation-dependent. The type named size_t is one of them: in one implementation it may be an unsigned int, while in another the same name may refer to an unsigned long. The written name looks identical in both places, but the type behind it is not guaranteed to be the same.
An Alias Is a Name, Not a New Type
A type alias is an alternative name for an existing type. It is not a new type. The alias is the name the programmer writes, and the underlying type is the existing type that the name stands for.
The direction of this relationship matters. Writing the alias is the same as writing the type it names. The alias gives the programmer a convenient label without changing what the type is. Nothing about the underlying type becomes different because it has been given a second name, so an alias should never be thought of as a separate kind of type with its own behavior.
Why an Implementation-Dependent Type Causes Trouble
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.
Consider what happens if code uses such a type by its underlying name. That code is tied to one particular implementation. When the program is moved to an implementation that defines the type differently, the written code no longer matches the underlying type everywhere it is used, and the programmer must find and change those lines. Repeated across a large program, this makes moving code between platforms slow and error-prone.
Tracing One Name Across Two Implementations
The name size_t is the running example here. The type it names is implementation-dependent. On one implementation, the name may refer to an unsigned int. On another, the same written name may refer to an unsigned long. A reader sees size_t in both places and reads the same text, but the underlying type behind that text is not the same everywhere.
How an Alias Keeps Code Unchanged
Here is the central benefit of the alias. 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. The programmer writes the alias once, and the choice of underlying type is made by the implementation.
Readers of the code also benefit. The alias names the purpose of the value, so a reader who sees size_t understands that the type has been chosen to suit the implementation. It is not a fixed choice made by the author of the code.
Worked Example: Moving a Program Between Implementations
Keeping a Program Portable
A team has a program that declares a value to hold a size or count using the alias size_t. They need to build the same program on a second implementation. Which lines of source text must change?
- 1Identify what the source names
Every declaration uses the alias size_t, not the underlying type name. The source text names the alias, not a concrete type.
- 2Recall what the alias stands for
The alias is only a label. On the second implementation it may stand for a different underlying type, but that choice is already handled by the implementation's definition of the alias.
- 3Check for hard-coded types
The team searches for the underlying type names written directly in the code. Any such line is tied to one implementation and would need editing.
- 4Conclude what changes
If the code uses only the alias, no declaration needs rewriting. The build simply uses the underlying type that the second implementation defines for that alias.
A program that writes only the alias keeps its source text unchanged when moved. Only hard-coded underlying type names would require edits.
Common Mistakes That Weaken Portability
Using an alias gives portability only when the code is written to use the alias consistently. The following mistakes undo the benefit even though an alias appears in the program.
Common mistake Writing the underlying type directly instead of the alias
What it looks likeDeclaring a variable with the underlying type name in one place and the alias in another
Why it failsWriting the underlying type ties that line to one implementation, so it will not follow the alias when the code moves to another implementation.
Do this insteadWrite the alias everywhere the value has that purpose.
Common mistake Assuming one fixed meaning for an alias
What it looks likeBelieving that size_t always refers to unsigned long because it did on one machine
Why it failsThe same alias can refer to different underlying types on different implementations, so an assumption based on one build is not reliable on another.
Do this insteadTreat the alias as a label whose underlying type is decided by the implementation, and do not rely on a particular underlying type.
Common mistake Treating the alias as a separate new type
Why it failsAn alias is an alternative name for an existing type. It does not create a new distinct type with its own rules.
Do this insteadReason about the alias by reasoning about the type it names.
| Approach | What the source text names | Effect when moved to another implementation |
|---|---|---|
| Using the alias size_t | The alias name | Source text stays the same; the implementation supplies the underlying type |
| Hard-coding an underlying type | A concrete type such as unsigned int | The line stays tied to one implementation and may need editing |
Using the alias versus hard-coding the underlying type
Practice: Choosing the Portable Form
A colleague's code declares a counter with the underlying type name unsigned long because it worked on their machine. Rewrite the idea in your own words: what should the declaration name instead, and why does that keep the code portable across implementations?
Hints
- Ask what the declaration is for: the purpose of the value is what the alias names.
- Think about whether the underlying type is fixed or decided by the implementation.
- Consider what must be edited if the program moves to an implementation where the underlying type differs.
Key Takeaways
- 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.
- Some types are implementation-dependent, so the same name such as size_t can refer to different underlying types on different implementations.
- Code that uses an alias rather than the underlying type name can be written once and reused across implementations without modification.
- Portability is weakened by hard-coding underlying types or by assuming one fixed meaning for an alias.