|
| 1 | +<div align=right> |
| 2 | + |
| 3 | + 🌎 [中文] | [English] |
| 4 | +</div> |
| 5 | + |
| 6 | +[中文]: ../../cpp11/14-type-alias.html |
| 7 | +[English]: ./14-type-alias.html |
| 8 | + |
| 9 | +# Type alias and alias template |
| 10 | + |
| 11 | +Type alias and alias template are important features introduced in C++11, used to create new names for existing types, enhancing the expressive power of generic programming, and improving code readability and maintainability. |
| 12 | + |
| 13 | +| Book | Video | Code | X | |
| 14 | +| --- | --- | --- | --- | |
| 15 | +| [cppreference-type-alias](https://en.cppreference.com/w/cpp/language/type_alias) / [markdown](https://github.com/Sunrisepeak/mcpp-standard/blob/main/book/en/src/cpp11/14-type-alias.md) | [Video Explanation]() | [Exercise Code](https://github.com/Sunrisepeak/mcpp-standard/blob/main/dslings/en/cpp11/14-type-alias-0.cpp) | | |
| 16 | + |
| 17 | +> Note: The `using` keyword existed before C++11, but was mainly used for namespace and class member declarations |
| 18 | +> - Declaring namespaces: `using namespace std;` |
| 19 | +> - Class member declarations: `struct B : A { using A::member; };` |
| 20 | +
|
| 21 | +**Why introduced?** |
| 22 | + |
| 23 | +- Replace traditional `typedef` syntax with a more intuitive way to define type aliases |
| 24 | +- Support template aliases, enhancing the expressive power of generic programming |
| 25 | +- Improve code readability, especially for complex types |
| 26 | +- Consistent with `using` declaration syntax |
| 27 | + |
| 28 | +**What's the difference between type alias and typedef?** |
| 29 | + |
| 30 | +- More intuitive syntax: `using NewType = OldType;` vs `typedef OldType NewType;` |
| 31 | +- Support template aliases, while `typedef` does not |
| 32 | +- More flexible and powerful in template programming |
| 33 | + |
| 34 | +## I. Basic Usage and Scenarios |
| 35 | + |
| 36 | +### Basic Type Alias |
| 37 | + |
| 38 | +> Create new names for existing types to improve code readability, and can replace traditional `typedef` alias definitions |
| 39 | +
|
| 40 | +```cpp |
| 41 | +typedef int Integer; // Traditional typedef way |
| 42 | +using Integer = int; // C++11 using way |
| 43 | + |
| 44 | +// Using aliases |
| 45 | +Integer i = 1; |
| 46 | +int j = 2; |
| 47 | +``` |
| 48 | + |
| 49 | +Type alias is not a new type, but an alias for other composite types, essentially the same. In the above code, the essence of `Integer` is `int`, commonly used to simplify type names. |
| 50 | + |
| 51 | +### Complex Type Alias |
| 52 | + |
| 53 | +> Create aliases for complex types (such as function pointers, nested types) |
| 54 | +
|
| 55 | +```cpp |
| 56 | +// Function pointer alias |
| 57 | +using FuncPtr = void(*)(int, int); |
| 58 | +using StringVector = std::vector<std::string>; |
| 59 | + |
| 60 | +// Nested type alias |
| 61 | +struct Container { |
| 62 | + using ValueType = int; |
| 63 | + using Iterator = std::vector<ValueType>::iterator; |
| 64 | +}; |
| 65 | + |
| 66 | +void example(int a, int b) { |
| 67 | + // Function implementation |
| 68 | +} |
| 69 | + |
| 70 | +int main() { |
| 71 | + FuncPtr func = example; // Equivalent: void(*func)(int, int) = example; |
| 72 | + StringVector strings = {"hello", "world"}; // Equivalent: std::vector<std::string> strings... |
| 73 | + Container::ValueType value = 100; // Equivalent: int value = 100; |
| 74 | + return 0; |
| 75 | +} |
| 76 | +``` |
| 77 | +
|
| 78 | +For code like `void (*func)(int, int) = example;`, many people might hesitate before understanding it defines a function pointer. By using `using` to give complex types a type alias `FuncPtr`, using `FuncPtr func = example;` allows people to quickly understand the code's intent. |
| 79 | +
|
| 80 | +### Alias Template |
| 81 | +
|
| 82 | +> Create aliases for template types, enhancing generic programming capabilities |
| 83 | +
|
| 84 | +```cpp |
| 85 | +// Alias template |
| 86 | +template <typename T> |
| 87 | +using Vec = std::vector<T>; |
| 88 | +
|
| 89 | +// Create "subset" alias types based on generics |
| 90 | +template <typename T> |
| 91 | +using Vec3 = std::array<T, 3>; |
| 92 | +template <typename T> |
| 93 | +using Vec4 = std::array<T, 4>; |
| 94 | +
|
| 95 | +// Alias template with default parameters |
| 96 | +template <typename T, typename Compare = std::less<T>> |
| 97 | +using Heap = std::priority_queue<T, std::vector<T>, Compare>; |
| 98 | +
|
| 99 | +int main() { |
| 100 | + Vec<int> numbers = {1, 2, 3}; |
| 101 | + Vec3<float> v3 = {1.0f, 2.0f, 3.0f}; |
| 102 | + Vec4<float> v4 = {1.0f, 2.0f, 3.0f, 4.0f}; |
| 103 | + Heap<int> minHeap; |
| 104 | + Heap<int, std::greater<int>> maxHeap; |
| 105 | + return 0; |
| 106 | +} |
| 107 | +``` |
| 108 | + |
| 109 | +In addition to creating aliases for complex types, it also supports creating aliases for template types, and through template parameters, it can control the parameters/properties of the original template type - default parameters, allocator types, length, comparators, etc. In the above code, we created dynamic Vec type aliases; also created fixed-length `Vec3`, `Vec4` type aliases for special scenarios (vector, matrix calculations) by specifying length; and used template parameter defaults to create `Heap` type, using `vector` as the underlying data structure by default, supporting default min-heap, and setting max-heap by specifying template parameters. |
| 110 | + |
| 111 | +### Standard Library _t Style Templates |
| 112 | + |
| 113 | +> In STL, some templates provide _t versions to save the process of manually obtaining types and values. Type aliases can easily implement them. _v style suuport by `c++ 17` [inline variables + variable templates] |
| 114 | + |
| 115 | +`Reference implementation of std::remove_const_t` |
| 116 | + |
| 117 | +```cpp |
| 118 | +// Implementation and principle explanation of remove_const can refer to: https://zhuanlan.zhihu.com/p/352972564 |
| 119 | +template <typename T> |
| 120 | +using my_remove_const_t = typename std::remove_const<T>::type; |
| 121 | + |
| 122 | +int main() { |
| 123 | + const int a = 10; |
| 124 | + my_remove_const_t<decltype(a)> b = a; // b's type is int, not const int |
| 125 | + return 0; |
| 126 | +} |
| 127 | +``` |
| 128 | + |
| 129 | +## II. Precautions |
| 130 | + |
| 131 | +### Alias is Not a New Type |
| 132 | + |
| 133 | +> Type alias is just a synonym for existing types and does not create new types |
| 134 | +
|
| 135 | +```cpp |
| 136 | +using MyInt = int; |
| 137 | +using YourInt = int; |
| 138 | + |
| 139 | +int main() { |
| 140 | + MyInt a = 10; |
| 141 | + YourInt b = 20; |
| 142 | + |
| 143 | + a = b; // Can assign because both are int types |
| 144 | + static_assert(std::is_same<MyInt, YourInt>::value, "Types are the same"); |
| 145 | + |
| 146 | + return 0; |
| 147 | +} |
| 148 | +``` |
| 149 | + |
| 150 | +### Scope of Template Aliases |
| 151 | + |
| 152 | +> Alias templates must be declared at class scope or namespace scope |
| 153 | +
|
| 154 | +```cpp |
| 155 | +namespace MyNamespace { |
| 156 | + template<typename T> |
| 157 | + using MyVector = std::vector<T>; |
| 158 | +} |
| 159 | + |
| 160 | +class MyClass { |
| 161 | +public: |
| 162 | + template<typename T> |
| 163 | + using Ptr = T*; |
| 164 | +}; |
| 165 | + |
| 166 | +// Error: cannot declare alias template in function scope |
| 167 | +// void func() { |
| 168 | +// template<typename T> |
| 169 | +// using LocalAlias = T; // Compilation error |
| 170 | +// } |
| 171 | +``` |
| 172 | +
|
| 173 | +### Recursive Alias Restrictions |
| 174 | +
|
| 175 | +> Alias templates cannot directly or indirectly reference themselves |
| 176 | +
|
| 177 | +```cpp |
| 178 | +template<typename T> |
| 179 | +struct A; |
| 180 | +
|
| 181 | +// Error: recursive alias |
| 182 | +// template<typename T> |
| 183 | +// using B = typename A<T>::U; |
| 184 | +
|
| 185 | +template<typename T> |
| 186 | +struct A { |
| 187 | + // typedef B<T> U; // This will cause recursive definition error |
| 188 | +}; |
| 189 | +``` |
| 190 | + |
| 191 | +## III. Exercise Code |
| 192 | + |
| 193 | +### Exercise Code Topics |
| 194 | + |
| 195 | +- 0 - [Basic Type Alias](https://github.com/Sunrisepeak/mcpp-standard/blob/main/dslings/en/cpp11/14-type-alias-0.cpp) |
| 196 | +- 1 - [Complex Types and Function Pointer Aliases](https://github.com/Sunrisepeak/mcpp-standard/blob/main/dslings/en/cpp11/14-type-alias-1.cpp) |
| 197 | +- 2 - [Alias Template Basics](https://github.com/Sunrisepeak/mcpp-standard/blob/main/dslings/en/cpp11/14-type-alias-2.cpp) |
| 198 | +- 3 - [Alias Template Applications in Standard Library](https://github.com/Sunrisepeak/mcpp-standard/blob/main/dslings/en/cpp11/14-type-alias-3.cpp) |
| 199 | + |
| 200 | +### Exercise Code Auto-Check Command |
| 201 | + |
| 202 | +```bash |
| 203 | +d2x checker type-alias |
| 204 | +``` |
| 205 | + |
| 206 | +## IV. Other |
| 207 | + |
| 208 | +- [Discussion Forum](https://forum.d2learn.org/category/20) |
| 209 | +- [mcpp-standard Tutorial Repository](https://github.com/Sunrisepeak/mcpp-standard) |
| 210 | +- [Tutorial Video List](https://space.bilibili.com/65858958/lists/5208246) |
| 211 | +- [Tutorial Support Tool - xlings](https://github.com/d2learn/xlings) |
0 commit comments