Type Aliases
A template alias is a name that stands for a template or a combination of template arguments.
Why Long Template Names Become Hard to Read
Templates let you write one pattern that works for many types. That flexibility has a cost: the names you write can grow long. A template that takes several type arguments, and that is itself built from other templates, can produce a declaration that is hard to scan. Every place the full name appears, a reader has to parse it again, and every place the name must change, a programmer has to change it.
Type aliases and template aliases are the C++ technique for dealing with this problem. In this article you will watch the state of a name change step by step: first, how a short name is attached to an existing type; second, how a template alias stands for a template with its arguments filled in; and third, how to decide whether an alias actually helps the code you are reading or writing.
A Second Name for the Same Type
A type alias is a synonym for a type or a template, declared with the keyword using. It gives an existing type or template a second name that means exactly the same thing.
Programs often refer to the same type many times. Sometimes it is useful to introduce a synonym for a type, which is a second name that means exactly the same thing. The same idea also applies to templates, not only to ordinary types. Once the alias exists, the original name and the new name refer to the same thing.
An alias is a second name for an existing type, so it does not create a separate type. It does not describe a new kind of value, and it does not change how the type behaves.
Reading the using Declaration
using type_alias = existing_type;- 1The keyword using begins the declaration.
- 2The new alias name,
type_alias, is introduced on the left of the equals sign. - 3The existing type,
existing_type, is written on the right of the equals sign. - 4The semicolon ends the declaration.
The general pattern is that the keyword using is followed by the new alias name, then an equals sign, then the existing type, and finally a semicolon. The alias name always goes on the left of the equals sign and the existing type always goes on the right. The diagram below labels each part of the source declaration. Notice that the existing type is the only thing that already exists before the line is read; the alias name is introduced by the declaration itself.
Tracing What size_t Refers To
The standard header <cstddef> contains a definition of the alias size_t. The source gives the following declaration as its example of a type alias. Read this line as: from now on, the name size_t is a synonym for unsigned int. Wherever size_t appears as a type, the compiler treats it exactly as it would treat unsigned int.
- The alias name is size_t, on the left of the equals sign.
- The existing type is unsigned int, on the right of the equals sign.
Using an alias for a double-precision distance
The following original illustration defines a new alias named distance_t for double, then uses that alias to declare a variable. What type does the variable have?
- 1Read the alias declaration
using distance_t = double; introduces distance_t as a second name for double.
- 2Read the variable declaration
distance_t trip = 12.5; declares trip with the name distance_t in the type position.
- 3Replace the alias with its meaning
Because distance_t is a synonym for double, the declaration means double trip = 12.5;.
- 4Check what changed
No new type was created. The variable behaves exactly like any other double.
trip is an ordinary double. The alias only changed the name used to write the type.
Template Aliases and Their Two Purposes
A template alias is a name that stands for a template or a combination of template arguments. The source states that template aliases serve two purposes: simplifying notation and hiding implementation details.
A template alias declaration has the same shape as a type alias declaration, with a template parameter list placed in front of it. The reader's first task is to find the right-hand side, because that is the actual meaning, and the left-hand side is simply the name chosen for it. In the generated example below, the alias Pairs takes one type parameter T and stands for Container with T and OtherPolicy as its arguments.
- template<typename T> says Pairs takes one type parameter.
- The right-hand side Container<T, OtherPolicy> is the original template with its arguments.
- Pairs<double> declares values whose type is Container<double, OtherPolicy>.
The mapping from alias arguments to original arguments is the part to check when reading. Whatever you write inside the angle brackets of the alias is substituted for the parameter on the right-hand side, so the full meaning is always the original template with those arguments in its argument list.
When an Alias Helps and When It Clutters
An alias is only worth introducing when it makes a declaration easier to understand or easier to change. An alias that is used once, and whose name adds nothing beyond the original, forces the reader to look up one more name to find the same type. The comparison below summarizes the difference.
| Situation | Alias helpful? | Reason |
|---|---|---|
| Long template-id repeated in many places | Yes | The alias is written once and read as one meaningful word |
| Implementation choice may change later | Yes | Clients depend on the alias, so the change is made in one declaration |
| Short type used in one place with an obvious name | Usually no | The alias adds a name the reader must look up without making the code clearer |
| Alias name describes nothing beyond the original | Usually no | The reader must still reason about the original type, so the extra name adds a layer |
Deciding whether an alias improves a declaration
Common mistake Reading the left-hand side as the meaning of the alias
What it looks likeIn using distance_t = double;, reading distance_t as the meaning and ignoring double.
Why it failsThe left-hand side is only the chosen name. The right-hand side holds the actual type.
Do this insteadFind the right-hand side first and substitute it for the alias name when tracing the code.
Common mistake Believing an alias creates a new type
What it looks likeExpecting size_t to behave differently from unsigned int because it has its own name.
Why it failsAn alias is a second name for an existing type. It does not create a separate type with different behavior.
Do this insteadTreat size_t exactly as unsigned int wherever it appears as a type.
Common mistake Forgetting to substitute template arguments into the right-hand side
What it looks likeReading Pairs<double> as Container<T, OtherPolicy> with T left unchanged.
Why it failsThe argument in the alias's angle brackets replaces the parameter on the right-hand side.
Do this insteadSubstitute double for T everywhere it appears on the right-hand side to get Container<double, OtherPolicy>.
Common mistake Adding an alias for a short type used once
Why it failsThe extra name forces a lookup without making the declaration clearer.
Do this insteadWrite the short type directly when the name adds nothing and the type appears only once.
Predicting What an Alias Means
What do you think happens?
Given the source declaration using size_t = unsigned int; what does the name size_t stand for?
Reveal answer
size_t is a synonym for unsigned int.
The alias gives the existing type unsigned int a second name. It does not create a new type, so size_t behaves exactly as unsigned int does wherever it is used as a type.
Given the declaration template<typename T> using Pairs = Container<T, OtherPolicy>;, write the full template-id that Pairs<double> stands for, and name the alias name and the existing template in the declaration.
Hints
- Find the right-hand side first: it holds the meaning.
- Substitute double for T everywhere it appears on the right-hand side.
- The alias name is on the left of the equals sign and the existing template is on the right.
Summary of Type Aliases
- 1A template alias is a name that stands for a template or a combination of template arguments, and it serves two purposes: simplifying notation and hiding implementation details.
- 2A type alias is a synonym for a type or a template, declared with the keyword using in the form using
new_name=existing_type; with the new name on the left and the existing type on the right. - 3An alias is a second name for the same type. It does not create a new type with different behavior.
- 4When reading an alias declaration, find the right-hand side first, since it holds the actual meaning, and substitute the alias arguments into it.
- 5Introduce an alias when it makes a long or repeated name easier to read or easier to change, and avoid an alias that only forces the reader to look up the same type under another name.
At a glance
- A template alias is a name that stands for a template or a combination of template arguments, and it serves two purposes: simplifying notation and hiding implementation details.
- A type alias is a synonym for a type or a template, declared with the keyword using in the form using
new_name=existing_type; with the new name on the left and the existing type on the right. - An alias is a second name for the same type. It does not create a new type with different behavior.
- When reading an alias declaration, find the right-hand side first, since it holds the actual meaning, and use the template parameter list to see how arguments flow into the original template.
- Introduce an alias when it makes a long or repeated name easier to read or easier to change, and avoid adding an alias that only forces the reader to look up the same type under another name.