diff --git a/book/en/src/SUMMARY.md b/book/en/src/SUMMARY.md index b2008be..41bd31f 100644 --- a/book/en/src/SUMMARY.md +++ b/book/en/src/SUMMARY.md @@ -31,6 +31,7 @@ # C++14 Core Language Features - [Generic Lambdas](./cpp14/00-generic-lambdas.md) +- [Return Type Deduction](./cpp14/03-return-type-deduction.md) # Additional Resources diff --git a/book/en/src/cpp14/03-return-type-deduction.md b/book/en/src/cpp14/03-return-type-deduction.md new file mode 100644 index 0000000..3e8f7fe --- /dev/null +++ b/book/en/src/cpp14/03-return-type-deduction.md @@ -0,0 +1,98 @@ +
+ + 🌎 [中文] | [English] +
+ +[中文]: ../../cpp14/03-return-type-deduction.html +[English]: ./03-return-type-deduction.html + +# Return Type Deduction + +C++14 allows functions to use `auto` as a return type without trailing `-> decltype(...)` + +| Book | Video | Code | X | +| --- | --- | --- | --- | +| [cppreference-auto](https://en.cppreference.com/w/cpp/language/auto) / [markdown](https://github.com/mcpp-community/d2mcpp/blob/main/book/en/src/cpp14/03-return-type-deduction.md) | [Video Explanation]() | [Exercise Code](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/en/cpp14/03-return-type-deduction-0.cpp) | | + + +**Why introduced?** + +- C++11 required `-> decltype(...)` trailing return for `auto` functions +- Many simple functions don't need an explicit return type + +## I. Basic Usage and Scenarios + +### auto return — plain functions + +```cpp +auto add(int a, int b) { // deduced as int + return a + b; +} +``` + +### auto return — template functions + +```cpp +template +auto multiply(T1 a, T2 b) { // C++14: no -> decltype needed + return a * b; +} +``` + +## II. Real-World Case — auto Return Deduction in the STL + +> The MSVC STL uses `auto` return types extensively to simplify template function signatures. The examples below cite the vendored [MSVC STL](https://github.com/mcpp-community/d2mcpp/tree/main/msvc-stl) (source: [`msvc-stl/stl/inc/xutility`](https://github.com/mcpp-community/d2mcpp/blob/main/msvc-stl/stl/inc/xutility#L1129-L1132)); `_NODISCARD` / `constexpr` are library-internal annotations + +### _To_unsigned_like — auto Return Simplifies Template Functions + +```cpp +// MSVC STL · msvc-stl/stl/inc/xutility (abridged) +template <_Integer_like _Ty> +_NODISCARD constexpr auto _To_unsigned_like(const _Ty _Value) noexcept { + return static_cast<_Make_unsigned_like_t<_Ty>>(_Value); +} +``` + +The return type is `_Make_unsigned_like_t<_Ty>` — without `auto`, the signature would be `_Make_unsigned_like_t<_Ty> _To_unsigned_like(...)`, with the return type longer than the function name. `auto` keeps the signature clean while the return statement naturally expresses the type + +## III. Notes + +### auto return requires consistent types + +```cpp +auto bad(int x) { + if (x > 0) return 1; // int + else return 2.0; // double → error! +} +``` + +### Recursion requires explicit return type + +```cpp +auto factorial(int n) { // error: recursive + return n <= 1 ? 1 : n * factorial(n - 1); +} +``` + +### auto return strips references + +Use `decltype(auto)` when you need to preserve references (see next chapter) + +## IV. Exercise Code + +### Exercise Topics + +- 0 - [auto Return Type Deduction](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/en/cpp14/03-return-type-deduction-0.cpp) + +### Auto-Checker Command + +``` +d2x checker return-type-deduction +``` + +## V. Other + +- [Discussion Forum](https://forum.d2learn.org/category/20) +- [d2mcpp Tutorial Repository](https://github.com/mcpp-community/d2mcpp) +- [Tutorial Video List](https://space.bilibili.com/65858958/lists/5208246) +- [Tutorial Support Tool - xlings](https://github.com/openxlings/xlings) diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 7efe83a..c110145 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -31,6 +31,7 @@ # C++14核心语言特性 - [泛型 lambda - generic lambdas](./cpp14/00-generic-lambdas.md) +- [返回类型推导 - return type deduction](./cpp14/03-return-type-deduction.md) # 其他 diff --git a/book/src/cpp14/03-return-type-deduction.md b/book/src/cpp14/03-return-type-deduction.md new file mode 100644 index 0000000..c694ba6 --- /dev/null +++ b/book/src/cpp14/03-return-type-deduction.md @@ -0,0 +1,98 @@ +
+ + 🌎 [中文] | [English] +
+ +[中文]: ./03-return-type-deduction.html +[English]: ../en/cpp14/03-return-type-deduction.html + +# 返回类型推导 - return type deduction + +C++14 允许函数使用 `auto` 作为返回类型而无需后置 `-> decltype(...)`, 编译器从 return 语句自动推导 + +| Book | Video | Code | X | +| --- | --- | --- | --- | +| [cppreference-auto](https://en.cppreference.com/w/cpp/language/auto) / [markdown](https://github.com/mcpp-community/d2mcpp/blob/main/book/src/cpp14/03-return-type-deduction.md) | [视频解读]() | [练习代码](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/cpp14/03-return-type-deduction-0.cpp) | | + + +**为什么引入?** + +- C++11 的 `auto` 返回类型必须配合 `-> decltype(...)` 后置语法 +- 很多简单函数不需要显式声明返回类型, 编译器可以从 return 语句推导出来 + +## 一、基础用法和场景 + +### auto 返回 — 普通函数 + +```cpp +auto add(int a, int b) { // 返回类型推导为 int + return a + b; +} +``` + +### auto 返回 — 模板函数 + +```cpp +template +auto multiply(T1 a, T2 b) { // C++14 不需要 -> decltype(a * b) + return a * b; +} +``` + +## 二、真实案例 - STL 中的 auto 返回推导 + +> MSVC STL 内部大量使用 `auto` 返回类型推导来简化模板函数签名。下面以仓库内置的 [MSVC STL](https://github.com/mcpp-community/d2mcpp/tree/main/msvc-stl) 为例 (源码: [`msvc-stl/stl/inc/xutility`](https://github.com/mcpp-community/d2mcpp/blob/main/msvc-stl/stl/inc/xutility#L1129-L1132)), `_NODISCARD` / `constexpr` 是库内部标注, 阅读时可忽略 + +### _To_unsigned_like — auto 返回简化模板函数 + +```cpp +// MSVC STL · msvc-stl/stl/inc/xutility (有删节) +template <_Integer_like _Ty> +_NODISCARD constexpr auto _To_unsigned_like(const _Ty _Value) noexcept { + return static_cast<_Make_unsigned_like_t<_Ty>>(_Value); +} +``` + +返回类型是 `_Make_unsigned_like_t<_Ty>`, 如果不写成 `auto`, 函数签名会变成 `_Make_unsigned_like_t<_Ty> _To_unsigned_like(...)`, 返回类型比函数名还长。`auto` 让签名简洁, 返回类型由 return 语句自然表达 + +## 三、注意事项 + +### auto 返回必须统一类型 + +```cpp +auto bad(int x) { + if (x > 0) return 1; // int + else return 2.0; // double → 错误! +} +``` + +### 递归需要显式返回类型 + +```cpp +auto factorial(int n) { // 错误: 递归, 无法推导 + return n <= 1 ? 1 : n * factorial(n - 1); +} +``` + +### auto 返回会剥离引用 + +需要保留引用时用 `decltype(auto)` (见下一章) + +## 四、练习代码 + +### 练习代码主题 + +- 0 - [auto 返回类型推导 — 普通函数和模板函数](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/cpp14/03-return-type-deduction-0.cpp) + +### 练习代码自动检测命令 + +``` +d2x checker return-type-deduction +``` + +## 五、其他 + +- [交流讨论](https://forum.d2learn.org/category/20) +- [d2mcpp教程仓库](https://github.com/mcpp-community/d2mcpp) +- [教程视频列表](https://space.bilibili.com/65858958/lists/5208246) +- [教程支持工具-xlings](https://github.com/openxlings/xlings) diff --git a/dslings/cpp14/03-return-type-deduction-0.cpp b/dslings/cpp14/03-return-type-deduction-0.cpp new file mode 100644 index 0000000..0b51000 --- /dev/null +++ b/dslings/cpp14/03-return-type-deduction-0.cpp @@ -0,0 +1,50 @@ +// d2mcpp: https://github.com/mcpp-community/d2mcpp +// license: Apache-2.0 +// file: dslings/cpp14/03-return-type-deduction-0.cpp +// +// Exercise/练习: cpp14 | 03 - return type deduction | auto 返回类型推导 +// +// Tips/提示: +// - C++14 允许 auto 作为返回类型, 无需后置 -> decltype(...) +// - 编译器从 return 语句推导返回类型 +// +// Docs/文档: +// - https://en.cppreference.com/w/cpp/language/auto +// - https://github.com/mcpp-community/d2mcpp/blob/main/book/src/cpp14/03-return-type-deduction.md +// +// 练习交流讨论: http://forum.d2learn.org/category/20 +// +// Auto-Checker/自动检测命令: +// +// d2x checker return-type-deduction +// + +#include +#include + +auto get_forty_two() { + return D2X_YOUR_ANSWER; +} + +auto greet(D2X_YOUR_ANSWER name) { + return "hello " + D2X_YOUR_ANSWER; +} + +template +D2X_YOUR_ANSWER max_of(T1 a, T2 b) { + return a > b ? a : b; +} + +int main() { + + d2x_assert_eq(get_forty_two(), 42); + + d2x_assert(greet(std::string("world")) == "hello world"); + + d2x_assert_eq(max_of(10, 20), 20); + d2x_assert_eq(max_of(2.5, D2X_YOUR_ANSWER), 3.5); + + D2X_WAIT + + return 0; +} diff --git a/dslings/cpp14/xmake.lua b/dslings/cpp14/xmake.lua index 8a21cbf..572bc65 100644 --- a/dslings/cpp14/xmake.lua +++ b/dslings/cpp14/xmake.lua @@ -9,3 +9,9 @@ target("cpp14-00-generic-lambdas-0") target("cpp14-00-generic-lambdas-1") set_kind("binary") add_files("00-generic-lambdas-1.cpp") + +-- target: cpp14-03-return-type-deduction + +target("cpp14-03-return-type-deduction-0") + set_kind("binary") + add_files("03-return-type-deduction-0.cpp") diff --git a/dslings/en/cpp14/03-return-type-deduction-0.cpp b/dslings/en/cpp14/03-return-type-deduction-0.cpp new file mode 100644 index 0000000..7af50f4 --- /dev/null +++ b/dslings/en/cpp14/03-return-type-deduction-0.cpp @@ -0,0 +1,50 @@ +// d2mcpp: https://github.com/mcpp-community/d2mcpp +// license: Apache-2.0 +// file: dslings/en/cpp14/03-return-type-deduction-0.cpp +// +// Exercise: cpp14 | 03 - return type deduction | auto return type deduction +// +// Tips: +// - C++14 allows auto as a return type without trailing -> decltype(...) +// - The compiler deduces the return type from the return statement +// +// Docs: +// - https://en.cppreference.com/w/cpp/language/auto +// - https://github.com/mcpp-community/d2mcpp/blob/main/book/en/src/cpp14/03-return-type-deduction.md +// +// Discussion Forum: http://forum.d2learn.org/category/20 +// +// Auto-Checker: +// +// d2x checker return-type-deduction +// + +#include +#include + +auto get_forty_two() { + return D2X_YOUR_ANSWER; +} + +auto greet(D2X_YOUR_ANSWER name) { + return "hello " + D2X_YOUR_ANSWER; +} + +template +D2X_YOUR_ANSWER max_of(T1 a, T2 b) { + return a > b ? a : b; +} + +int main() { + + d2x_assert_eq(get_forty_two(), 42); + + d2x_assert(greet(std::string("world")) == "hello world"); + + d2x_assert_eq(max_of(10, 20), 20); + d2x_assert_eq(max_of(2.5, D2X_YOUR_ANSWER), 3.5); + + D2X_WAIT + + return 0; +} diff --git a/dslings/en/cpp14/xmake.lua b/dslings/en/cpp14/xmake.lua index 8a21cbf..572bc65 100644 --- a/dslings/en/cpp14/xmake.lua +++ b/dslings/en/cpp14/xmake.lua @@ -9,3 +9,9 @@ target("cpp14-00-generic-lambdas-0") target("cpp14-00-generic-lambdas-1") set_kind("binary") add_files("00-generic-lambdas-1.cpp") + +-- target: cpp14-03-return-type-deduction + +target("cpp14-03-return-type-deduction-0") + set_kind("binary") + add_files("03-return-type-deduction-0.cpp") diff --git a/solutions/cpp14/03-return-type-deduction-0.cpp b/solutions/cpp14/03-return-type-deduction-0.cpp new file mode 100644 index 0000000..dceda1a --- /dev/null +++ b/solutions/cpp14/03-return-type-deduction-0.cpp @@ -0,0 +1,35 @@ +// d2mcpp: https://github.com/mcpp-community/d2mcpp +// license: Apache-2.0 +// reference solution for: dslings/cpp14/03-return-type-deduction-0.cpp +// +// 用途: 仅给 CI 与维护者参考使用,不是教程入口。 +// 教程练习入口: dslings/cpp14/03-return-type-deduction-0.cpp +// + +#include +#include + +auto get_forty_two() { + return 42; +} + +auto greet(const std::string& name) { + return "hello " + name; +} + +template +auto max_of(T1 a, T2 b) { + return a > b ? a : b; +} + +int main() { + + d2x_assert_eq(get_forty_two(), 42); + + d2x_assert(greet(std::string("world")) == "hello world"); + + d2x_assert_eq(max_of(10, 20), 20); + d2x_assert_eq(max_of(2.5, 3.5), 3.5); + + return 0; +} diff --git a/solutions/cpp14/xmake.lua b/solutions/cpp14/xmake.lua index 8bbbb90..d246660 100644 --- a/solutions/cpp14/xmake.lua +++ b/solutions/cpp14/xmake.lua @@ -9,3 +9,9 @@ target("cpp14-00-generic-lambdas-0-ref") target("cpp14-00-generic-lambdas-1-ref") set_kind("binary") add_files("00-generic-lambdas-1.cpp") + +-- target: cpp14-03-return-type-deduction + +target("cpp14-03-return-type-deduction-0-ref") + set_kind("binary") + add_files("03-return-type-deduction-0.cpp")