Skip to content
Theory · Casts and Aliases · lesson 5 of 7

Type aliases: using and typedef

Many people have a name and a nickname: friends call Alexander "Sasha", yet there is still only one person. A type alias is the same kind of second name for an existing type. The compiler sees the very same type behind it, while a short, clear name helps you read the code.

Why is this useful? The name long long says nothing about the variable holding a player's score, and std::vector<long long> takes a while to write in every declaration.

Two ways to write an alias

With using

An alias is introduced with using: using Score = long long;. The new name is to the left of =, as in an assignment, and the type it stands for is on the right.

With typedef

The older notation for the same alias comes from C: typedef long long Score;. There the new name comes last, after the type.

Let's see both notations in one program:

C++
#include <iostream>
#include <vector>

using Score = long long;
typedef std::vector<Score> ScoreList;

int main() {
    ScoreList scores{1500000000, 1500000000};
    Score total = scores[0] + scores[1];
    std::cout << total << '\n';  // 3000000000
}

Step by step:

  1. using Score = long long;: Score now means long long.
  2. typedef std::vector<Score> ScoreList;: ScoreList means std::vector<long long>, so an alias can be built from another alias.
  3. The sum of two 1500000000 values would not fit in an int, but Score is long long, so the program prints 3000000000.

The same type under another name

An alias does not create a new type: to the compiler, Score is long long, and ScoreList is std::vector<long long>. Values under the old name and the new one mix freely in one expression.

What an alias does give you is clearer code: to change the type for the whole program, you edit one using line.

Unlike #define, an alias obeys scope: declared inside a function, it is visible only there. This is where the nickname analogy ends: a person keeps a nickname everywhere, while such an alias disappears past the function's closing brace.

Common mistake

Aliases are expected to guard against mixing up units:

C++
#include <iostream>

using Celsius = double;
using Fahrenheit = double;

void print_celsius(Celsius t) {
    std::cout << t << '\n';
}

int main() {
    Fahrenheit boiling = 212.0;
    print_celsius(boiling);  // ✗
}

The compiler builds the program silently, and it prints 212 as a Celsius temperature. Celsius and Fahrenheit are both declared as aliases of double, so a function with a Celsius parameter accepts a Fahrenheit without a single warning. An alias does not protect against this mistake: keep the unit in the variable's name, such as boiling_f, so the mix-up shows when you read the code.

Key points

  • A type alias is a second name for an existing type: using Score = long long;.
  • typedef long long Score; is the older notation for the same alias, with the new name last.
  • An alias does not create a new type: values of two double aliases mix freely.
  • An alias obeys scope, and #define does not.

Subscribe to take the course

The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.

Sign in another way