You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: book/en/src/cpp11/00-auto-and-decltype.md
+105-5Lines changed: 105 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -44,7 +44,7 @@ decltype(b) b3; // Can be used without initialization
44
44
45
45
> Often used for complex expression type deduction to ensure calculation precision
46
46
47
-
```c++
47
+
```cpp
48
48
int a = 1;
49
49
50
50
auto b1 = a + 2;
@@ -58,7 +58,7 @@ decltype(2 + 'a') c2 = 2 + 'a';
58
58
59
59
**Iterator Type Deduction**
60
60
61
-
```c++
61
+
```cpp
62
62
std::vector<int> v = {1, 2, 3};
63
63
64
64
auto it = v.begin(); // Automatically deduce iterator type
@@ -72,7 +72,7 @@ for (; it != v.end(); ++it) {
72
72
73
73
> For complex types like functions or lambda expressions, auto and decltype are commonly used. Generally, lambda definitions use auto, while template type parameters use decltype.
74
74
75
-
```c++
75
+
```cpp
76
76
intadd_func(int a, int b) {
77
77
return a + b;
78
78
}
@@ -135,7 +135,65 @@ int main() {
135
135
}
136
136
```
137
137
138
-
## II. Important Notes - The Impact of Parentheses
138
+
## II. Real-World Case - auto/decltype in the STL
139
+
140
+
> The examples above illustrate syntax; the real value of auto/decltype shows up most directly in the standard library's own implementation. Below we use the in-repo [MSVC STL](https://github.com/mcpp-community/d2mcpp/tree/main/msvc-stl) as the source ([`msvc-stl/stl/inc/xutility`](https://github.com/mcpp-community/d2mcpp/blob/main/msvc-stl/stl/inc/xutility#L2200-L2235)); `_EXPORT_STD` / `_NODISCARD` / `_CONSTEXPR17` / `_STD` are internal library macros — ignore them when reading.
141
+
142
+
### Trailing return type + decltype: std::begin / std::end
143
+
144
+
`std::begin` / `std::end` (added in C++11) must adapt to any container; their return type depends entirely on `_Cont.begin()` and cannot be written ahead of time, so they "borrow" it via `auto ... -> decltype(...)`
_NODISCARD _CONSTEXPR17 auto end(_Container& _Cont) noexcept(noexcept(_Cont.end())) -> decltype(_Cont.end()) {
155
+
return _Cont.end();
156
+
}
157
+
```
158
+
159
+
This is exactly the trailing-return form from the "Function Return Type Deduction" section, living inside the standard library itself: `auto` as the placeholder + `decltype(_Cont.begin())` precisely deducing the differing iterator types of `vector<int>`, `list<T>`, and so on.
160
+
161
+
### Reusing another function's return type with decltype: std::cbegin / std::cend
162
+
163
+
Going further, `std::cbegin` simply reuses `begin`'s return type via `decltype(_STD begin(_Cont))` — it doesn't care what that type is, only that it "matches what begin returns"
_NODISCARD constexpr auto cbegin(const _Container& _Cont) noexcept(noexcept(_STD begin(_Cont)))
169
+
-> decltype(_STD begin(_Cont)) {
170
+
return _STD begin(_Cont);
171
+
}
172
+
```
173
+
174
+
> Takeaway: when a type "is decided by template parameters and simply cannot be written by hand", the standard library reaches for exactly the auto + decltype toolkit taught in this chapter — one of the core motivations for introducing them in C++11.
175
+
176
+
## III. Important Notes
177
+
178
+
### auto and const / reference stripping
179
+
180
+
> auto deduction **strips top-level const and references**; to keep them you must write `const auto&` / `auto&` explicitly, whereas decltype preserves the declared type exactly
181
+
182
+
```cpp
183
+
constint ci = 1;
184
+
int n = 2;
185
+
int& ri = n;
186
+
187
+
auto a = ci; // int — top-level const stripped
188
+
auto b = ri; // int — reference stripped (b is an independent copy of n)
0 commit comments