Type Aliases and Typedefs
Type aliases give a new name to an existing type.
Type aliases DO NOT declare a new type. For example, if you alias int as power and score, C++ will not complain if you assign score to power or power to score. (The compiler simply sees both "types" as int.)
Defining type aliases
using vs typedef
It's advised to use using as opposed to typedef:
- The syntax with
usingis easier to read when dealing with pointer-to-function - You can't use templates with
typedef
There are two ways to define type aliases:
- using (type alias) —
using <alias> = <type>, e.g.using number = int; - typedef —
typedef <type> <alias>, e.g.typedef int number
Using using
Simple example
int main() {
// "I'm using this alias as this type"
using km_type = double;
using kmph_type = double;
// Defining variables with the aliased types
km_type distance = 20;
kmph_type speed = 40.0;
}
With pointer to function
int add(int a, int b) {
return a + b;
}
int main() {
// Aliasing pointer to function
using int_op_ptr_type = int(*)(int, int);
// The following line has the same meaning as:
// int (*add_ptr)(int, int) = &add;
int_op_ptr_type add_ptr = &add;
}
With template
template <typename T, typename U>
struct Pair {
T first;
U second;
};
// Using the `template` keyword only works
// in the global scope (outside functions)
template <typename T>
using pair_type = Pair<T, T>;
int main() {
pair_type<int> pair = { 1, 2 };
printf("%d\n", pair.first); //=> 1
printf("%d\n", pair.second); //=> 2
}
Using typedef
Simple example
int main() {
// "I'm defining a new alias for this `type`: `alias`"
typedef double km_type;
typedef double kmph_type;
// Defining variables with the aliased types
km_type distance = 20;
kmph_type speed = 40.0;
}
With pointer to function
int add(int a, int b) {
return a + b;
}
int main() {
// Aliasing pointer to function
// The name of the alias is `int_op_ptr_type`
// (Yeah, the syntax kinda sucks.)
typedef int (*int_op_ptr_type)(int, int) ;
// The following line has the same meaning as:
// int (*add_ptr)(int, int) = &add;
int_op_ptr_type add_ptr = &add;
}
Scope of type aliases
They can have block scope or file scope, depending on where they are declared:
- if they are declared inside a block/function, they will have block scope;
- if they are declared outside any function, they will have file scope.
Real world usages
Simplifying complex types
Type aliases can simplify writing a complex type in your code. For example, you can refer to std::vector<std::pair<int, int>> simply as array_pair_int_type.
Adding meaning to "generic" types
For example, you can differentiate int to be student_id_type or time_seconds_type.
(Note that it's only for code legibility and from the compiler's perspective, they are all just int's.)
Platform-independent coding
For example, it can happen that on some platforms, int is 2 bytes, while on others, it is 4 bytes. (C++ spec does not specify the exact size for char, short, int, and long.)
So, using int can behave differently on different platforms. Instead, you can introduce types that includes their sizes and use them instead (a common practice in cross-platform programming, learncpp.com):
// Assuming `INT_2_BYTES` is `#defined`
// on machines where `int` is 2 bytes
// (it will use the top set of rules)
#ifdef INT_2_BYTES
using int8_t = char;
using int16_t = int;
using int32_t = long;
#else
using int8_t = char;
using int16_t = short;
using int32_t = int;
#endif
References
- 8.6 — Typedefs and type aliases — https://www.learncpp.com/cpp-tutorial/typedefs-and-type-aliases/
- Alias Templates and Template Parameters — https://www.modernescpp.com/index.php/alias-templates-and-template-parameters