Type Aliases and Alias Templates in C++
This article provides a practical overview of type aliases and alias
templates introduced in C++11 using the using syntax. You
will learn the fundamental syntax of modern type aliases, how they
compare to traditional typedef declarations, and how alias
templates solve long-standing metaprogramming limitations by allowing
parameterized type synonyms.
What is a Type Alias?
A type alias is an alternative name for an existing data type. In
modern C++, type aliases are declared using the using
keyword followed by the identifier name and the target type.
using Integer = int;
using StringList = std::vector<std::string>;Once defined, Integer and StringList can be
used interchangeably with their underlying types. They do not introduce
new distinct types; they are purely synonyms evaluated at compile
time.
Advantages Over
typedef
Prior to C++11, creating type synonyms required the
typedef keyword:
typedef int Integer;
typedef void (*FunctionPointer)(int, double);While functional, typedef syntax becomes difficult to
read when dealing with complex types, such as function pointers or
arrays. The using syntax aligns with standard variable
assignment syntax (name = value):
using FunctionPointer = void (*)(int, double);The identifier always appears on the left side of the assignment operator, making definitions significantly easier to parse visually.
What are Alias Templates?
The most critical advantage of the using syntax is its
native support for templates. An alias template allows you to define a
family of type aliases parameterized by one or more template
arguments.
Prior to C++11, creating a templated alias using typedef
required wrapping it in a templated struct:
// C++98 workaround
template <typename T>
struct StringMap {
typedef std::map<std::string, T> type;
};
// Usage
StringMap<int>::type myMap;With modern C++, alias templates achieve this directly and cleanly:
// Modern C++
template <typename T>
using StringMap = std::map<std::string, T>;
// Usage
StringMap<int> myMap;Advanced Template Specialization
Alias templates can also bind specific arguments while leaving others generic. For example, fixing an allocator or a key type for standard library containers:
template <typename Value>
using IntKeyMap = std::map<int, Value, std::greater<int>>;
IntKeyMap<std::string> scores; // std::map<int, std::string, std::greater<int>>Standard Library Adoption
The C++ standard library heavily utilizes alias templates. Starting
in C++14, standard type traits provide alias templates ending in
_t to replace the verbose
typename std::trait<T>::type idiom:
// C++11 style
typename std::decay<T>::type value1;
// Modern style using standard alias template
std::decay_t<T> value2;Under the hood, the standard library implements these using the exact same mechanism:
namespace std {
template <typename T>
using decay_t = typename decay<T>::type;
}Summary
- Type Aliases (
using NewName = Type;): Provide clean, readable synonyms for existing types, directly replacingtypedef. - Alias Templates
(
template <...> using NewName = Type<...>;): Allow type synonyms to accept template parameters, eliminating the need for nestedstructworkarounds.