-
Notifications
You must be signed in to change notification settings - Fork 115
feat(cpp14): add 02-variable-templates book chapter, exercises, solutions, and build wiring #76
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
lczllx
wants to merge
1
commit into
mcpp-community:main
from
lczllx:feat/cpp14-02-variable-templates
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
96 changes: 96 additions & 0 deletions
book/en/src/cpp14/02-variable-templates.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| <div align=right> | ||
|
|
||
| 🌎 [中文] | [English] | ||
| </div> | ||
|
|
||
| [中文]: ../../cpp14/02-variable-templates.html | ||
| [English]: ./02-variable-templates.html | ||
|
|
||
| # Variable Templates | ||
|
|
||
| C++14 introduces variable templates — allowing variables themselves to be parameterized by types | ||
|
|
||
| | Book | Video | Code | X | | ||
| | --- | --- | --- | --- | | ||
| | [cppreference-variable_template](https://en.cppreference.com/w/cpp/language/variable_template) / [markdown](https://github.com/mcpp-community/d2mcpp/blob/main/book/en/src/cpp14/02-variable-templates.md) | [Video Explanation]() | [Exercise Code](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/en/cpp14/02-variable-templates-0.cpp) | | | ||
|
|
||
|
|
||
| **Why introduced?** | ||
|
|
||
| - In C++11, templates could only be applied to functions and classes | ||
| - Type traits required some_trait<T>::value everywhere | ||
| - C++14 variable templates enable pi<double> / is_same_v<T, U> syntax | ||
|
|
||
| ## I. Basic Usage and Scenarios | ||
|
|
||
| ### Basic Variable Template | ||
|
|
||
| ```cpp | ||
| template <typename T> | ||
| constexpr T pi = T(3.1415926535897932385); | ||
|
|
||
| double d = pi<double>; // 3.1415926535897932385 | ||
| float f = pi<float>; // 3.14159265f | ||
| ``` | ||
|
|
||
| ### _v Type Traits | ||
|
|
||
| ```cpp | ||
| template <typename T, typename U> | ||
| constexpr bool is_same_v = std::is_same<T, U>::value; | ||
| ``` | ||
|
|
||
| ### Recursive Variable Templates | ||
|
|
||
| ```cpp | ||
| template <int N> | ||
| constexpr int factorial_v = N * factorial_v<N - 1>; | ||
|
|
||
| template <> | ||
| constexpr int factorial_v<0> = 1; | ||
| ``` | ||
|
|
||
| ## II. Real-World Case — Variable Templates in the STL | ||
|
|
||
| > The MSVC STL uses variable templates internally to replace the old `::value` trait pattern. The example below cites 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#L1458-L1462)) | ||
|
|
||
| ### _Is_iterator_v — Variable Templates Simplify Type Traits | ||
|
|
||
| ```cpp | ||
| // MSVC STL · msvc-stl/stl/inc/xutility (abridged) | ||
| template <class _Ty, class = void> | ||
| constexpr bool _Is_iterator_v = false; | ||
|
|
||
| template <class _Ty> | ||
| constexpr bool _Is_iterator_v<_Ty, void_t<_Iter_cat_t<_Ty>>> = true; | ||
|
|
||
| // External code uses _Is_iterator_v<_Ty> directly, no ::value needed | ||
| template <class _Ty> | ||
| struct _Is_iterator : bool_constant<_Is_iterator_v<_Ty>> {}; | ||
| ``` | ||
|
|
||
| `_Is_iterator_v` is a variable template — defaulting to false, with a specialization to true when `_Ty` has an `_Iter_cat_t`, replacing the traditional `_Is_iterator<T>::value` pattern. The variable template language mechanism introduced in C++14 enabled the STL to replace `::value` trait classes with `_v`-suffixed variables, paving the way for C++17 standardized `_v` traits like `is_same_v` | ||
|
|
||
| ## III. Notes | ||
|
|
||
| Variable templates support both full and partial specialization (unlike function templates, which only support full specialization). Don't overuse. | ||
|
|
||
| ## IV. Exercise Code | ||
|
|
||
| ### Exercise Topics | ||
|
|
||
| - 0 - [Basic Variable Templates — pi constant and compile-time config](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/en/cpp14/02-variable-templates-0.cpp) | ||
| - 1 - [_v Type Traits — implementing is_void_v and is_same_v](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/en/cpp14/02-variable-templates-1.cpp) | ||
|
|
||
| ### Auto-Checker Command | ||
|
|
||
| ``` | ||
| d2x checker variable-templates | ||
| ``` | ||
|
|
||
| ## 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) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 112 additions & 0 deletions
book/src/cpp14/02-variable-templates.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| <div align=right> | ||
|
|
||
| 🌎 [中文] | [English] | ||
| </div> | ||
|
|
||
| [中文]: ./02-variable-templates.html | ||
| [English]: ../en/cpp14/02-variable-templates.html | ||
|
|
||
| # 变量模板 - variable templates | ||
|
|
||
| 变量模板是 C++14 引入的语法扩展, 允许变量本身成为模板, 在特化时根据类型参数产生不同的值或对象 | ||
|
|
||
| | Book | Video | Code | X | | ||
| | --- | --- | --- | --- | | ||
| | [cppreference-variable_template](https://en.cppreference.com/w/cpp/language/variable_template) / [markdown](https://github.com/mcpp-community/d2mcpp/blob/main/book/src/cpp14/02-variable-templates.md) | [视频解读]() | [练习代码](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/cpp14/02-variable-templates-0.cpp) | | | ||
|
|
||
|
|
||
| **为什么引入?** | ||
|
|
||
| - C++11 的模板只能套在函数和类上, 数值常量只能写成 static constexpr 成员或枚举 | ||
| - 类型萃取大量使用 some_trait<T>::value, 每次都要写 ::value 后缀 | ||
| - C++14 变量模板让 pi<double> / is_same_v<T, U> 这种写法成为可能 | ||
|
|
||
| ## 一、基础用法和场景 | ||
|
|
||
| ### 基本变量模板 | ||
|
|
||
| ```cpp | ||
| template <typename T> | ||
| constexpr T pi = T(3.1415926535897932385); | ||
|
|
||
| double d = pi<double>; // 3.1415926535897932385 | ||
| float f = pi<float>; // 3.14159265f | ||
| int i = pi<int>; // 3 | ||
| ``` | ||
|
|
||
| ### 类型萃取 _v 后缀 | ||
|
|
||
| ```cpp | ||
| template <typename T, typename U> | ||
| constexpr bool is_same_v = std::is_same<T, U>::value; | ||
|
|
||
| static_assert(is_same_v<int, int>, ""); | ||
| static_assert(!is_same_v<int, float>, ""); | ||
| ``` | ||
|
|
||
| ### 编译期配置值 | ||
|
|
||
| ```cpp | ||
| template <typename T> | ||
| constexpr size_t max_buffer_size = 1024; | ||
|
|
||
| template <> | ||
| constexpr size_t max_buffer_size<double> = 4096; | ||
| ``` | ||
|
|
||
| ### 递归变量模板 | ||
|
|
||
| ```cpp | ||
| template <int N> | ||
| constexpr int factorial_v = N * factorial_v<N - 1>; | ||
|
|
||
| template <> | ||
| constexpr int factorial_v<0> = 1; | ||
|
|
||
| static_assert(factorial_v<5> == 120, ""); | ||
| ``` | ||
|
|
||
| ## 二、真实案例 - STL 中的变量模板 | ||
|
|
||
| > MSVC STL 内部大量使用变量模板替代旧的 `::value` 萃取类。下面以仓库内置的 [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#L1458-L1462)) | ||
|
|
||
| ### _Is_iterator_v — 变量模板简化类型萃取 | ||
|
|
||
| ```cpp | ||
| // MSVC STL · msvc-stl/stl/inc/xutility (有删节) | ||
| template <class _Ty, class = void> | ||
| constexpr bool _Is_iterator_v = false; | ||
|
|
||
| template <class _Ty> | ||
| constexpr bool _Is_iterator_v<_Ty, void_t<_Iter_cat_t<_Ty>>> = true; | ||
|
|
||
| // 外部通过 _Is_iterator_v<_Ty> 直接使用, 无需 ::value | ||
| template <class _Ty> | ||
| struct _Is_iterator : bool_constant<_Is_iterator_v<_Ty>> {}; | ||
| ``` | ||
|
|
||
| `_Is_iterator_v` 是变量模板 — 默认 false, 当 `_Ty` 拥有 `_Iter_cat_t` 时偏特化为 true, 替代了传统的 `_Is_iterator<T>::value` 写法。C++14 引入的变量模板语言机制, 让 STL 可以用 `_v` 后缀变量替代 `::value` 萃取类, 为 C++17 标准化 `is_same_v` 等 `_v` 萃取铺平了道路 | ||
|
|
||
| ## 三、注意事项 | ||
|
|
||
| 变量模板支持全特化和偏特化(这与函数模板不同, 后者只能全特化)。不要滥用 — 有些值用 constexpr 就够了。 | ||
|
|
||
| ## 四、练习代码 | ||
|
|
||
| ### 练习代码主题 | ||
|
|
||
| - 0 - [变量模板基础 — pi 常量和编译期配置值](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/cpp14/02-variable-templates-0.cpp) | ||
| - 1 - [类型萃取 _v 后缀 — 实现 is_void_v 和 is_same_v](https://github.com/mcpp-community/d2mcpp/blob/main/dslings/cpp14/02-variable-templates-1.cpp) | ||
|
|
||
| ### 练习代码自动检测命令 | ||
|
|
||
| ``` | ||
| d2x checker variable-templates | ||
| ``` | ||
|
|
||
| ## 五、其他 | ||
|
|
||
| - [交流讨论](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) |
46 changes: 46 additions & 0 deletions
dslings/cpp14/02-variable-templates-0.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| // d2mcpp: https://github.com/mcpp-community/d2mcpp | ||
| // license: Apache-2.0 | ||
| // file: dslings/cpp14/02-variable-templates-0.cpp | ||
| // | ||
| // Exercise/练习: cpp14 | 02 - variable templates | 变量模板基础 | ||
| // | ||
| // Tips/提示: | ||
| // - 变量模板用类型参数控制变量的值 | ||
| // - template<typename T> constexpr T name = ...; | ||
| // | ||
| // Docs/文档: | ||
| // - https://en.cppreference.com/w/cpp/language/variable_template | ||
| // - https://github.com/mcpp-community/d2mcpp/blob/main/book/src/cpp14/02-variable-templates.md | ||
| // | ||
| // 练习交流讨论: http://forum.d2learn.org/category/20 | ||
| // | ||
| // Auto-Checker/自动检测命令: | ||
| // | ||
| // d2x checker variable-templates | ||
| // | ||
|
|
||
| #include <d2x/cpp/common.hpp> | ||
|
|
||
| template <typename T> | ||
| constexpr D2X_YOUR_ANSWER pi = T(3.1415926535897932385); | ||
|
|
||
| template <typename T> | ||
| constexpr size_t max_buffer = D2X_YOUR_ANSWER; | ||
|
|
||
| template <> | ||
| constexpr size_t max_buffer<D2X_YOUR_ANSWER> = 4096; | ||
|
|
||
| int main() { | ||
|
|
||
| d2x_assert_eq(pi<double>, 3.1415926535897932385); | ||
| d2x_assert(pi<float> > 3.14f); | ||
| d2x_assert(pi<float> < 3.142f); | ||
|
|
||
| d2x_assert_eq(max_buffer<int>, 1024); | ||
| d2x_assert_eq(max_buffer<char>, 1024); | ||
| d2x_assert_eq(max_buffer<double>, D2X_YOUR_ANSWER); | ||
|
|
||
| D2X_WAIT | ||
|
|
||
| return 0; | ||
| } |
56 changes: 56 additions & 0 deletions
dslings/cpp14/02-variable-templates-1.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| // d2mcpp: https://github.com/mcpp-community/d2mcpp | ||
| // license: Apache-2.0 | ||
| // file: dslings/cpp14/02-variable-templates-1.cpp | ||
| // | ||
| // Exercise/练习: cpp14 | 02 - variable templates | _v 类型萃取 | ||
| // | ||
| // Tips/提示: | ||
| // - _v 后缀的类型萃取本质就是变量模板, 省去了 ::value | ||
| // - template<typename T> constexpr bool xxx_v = xxx<T>::value; | ||
| // | ||
| // Docs/文档: | ||
| // - https://en.cppreference.com/w/cpp/language/variable_template | ||
| // - https://github.com/mcpp-community/d2mcpp/blob/main/book/src/cpp14/02-variable-templates.md | ||
| // | ||
| // 练习交流讨论: http://forum.d2learn.org/category/20 | ||
| // | ||
| // Auto-Checker/自动检测命令: | ||
| // | ||
| // d2x checker variable-templates | ||
| // | ||
|
|
||
| #include <d2x/cpp/common.hpp> | ||
| #include <type_traits> | ||
|
|
||
| template <typename T> | ||
| constexpr bool is_void_v = D2X_YOUR_ANSWER; | ||
|
|
||
| template <typename T, typename U> | ||
| constexpr D2X_YOUR_ANSWER is_same_v = std::is_same<T, U>::value; | ||
|
|
||
| template <int N> | ||
| constexpr int factorial_v = D2X_YOUR_ANSWER; | ||
|
|
||
| template <> | ||
| constexpr int factorial_v<0> = D2X_YOUR_ANSWER; | ||
|
|
||
| int main() { | ||
|
|
||
| static_assert(is_void_v<void>, ""); | ||
| d2x_assert(is_void_v<void>); | ||
| d2x_assert(!is_void_v<int>); | ||
|
|
||
| static_assert(is_same_v<int, int>, ""); | ||
| d2x_assert((is_same_v<int, int>)); | ||
| d2x_assert((!is_same_v<int, float>)); | ||
| d2x_assert((is_same_v<D2X_YOUR_ANSWER, char>)); | ||
|
|
||
| static_assert(factorial_v<5> == 120, ""); | ||
| d2x_assert_eq(factorial_v<5>, 120); | ||
| d2x_assert_eq(factorial_v<0>, 1); | ||
| d2x_assert_eq(factorial_v<3>, 6); | ||
|
|
||
| D2X_WAIT | ||
|
|
||
| return 0; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
dslings/en/cpp14/02-variable-templates-0.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| // d2mcpp: https://github.com/mcpp-community/d2mcpp | ||
| // license: Apache-2.0 | ||
| // file: dslings/en/cpp14/02-variable-templates-0.cpp | ||
| // | ||
| // Exercise: cpp14 | 02 - variable templates | basic variable templates | ||
| // | ||
| // Tips: | ||
| // - Variable templates use type parameters to control values | ||
| // - template<typename T> constexpr T name = ...; | ||
| // | ||
| // Docs: | ||
| // - https://en.cppreference.com/w/cpp/language/variable_template | ||
| // - https://github.com/mcpp-community/d2mcpp/blob/main/book/en/src/cpp14/02-variable-templates.md | ||
| // | ||
| // Discussion Forum: http://forum.d2learn.org/category/20 | ||
| // | ||
| // Auto-Checker: | ||
| // | ||
| // d2x checker variable-templates | ||
| // | ||
|
|
||
| #include <d2x/cpp/common.hpp> | ||
|
|
||
| template <typename T> | ||
| constexpr D2X_YOUR_ANSWER pi = T(3.1415926535897932385); | ||
|
|
||
| template <typename T> | ||
| constexpr size_t max_buffer = D2X_YOUR_ANSWER; | ||
|
|
||
| template <> | ||
| constexpr size_t max_buffer<D2X_YOUR_ANSWER> = 4096; | ||
|
|
||
| int main() { | ||
|
|
||
| d2x_assert_eq(pi<double>, 3.1415926535897932385); | ||
| d2x_assert(pi<float> > 3.14f); | ||
| d2x_assert(pi<float> < 3.142f); | ||
|
|
||
| d2x_assert_eq(max_buffer<int>, 1024); | ||
| d2x_assert_eq(max_buffer<char>, 1024); | ||
| d2x_assert_eq(max_buffer<double>, D2X_YOUR_ANSWER); | ||
|
|
||
| D2X_WAIT | ||
|
|
||
| return 0; | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.