diff --git "a/code/04\346\230\276\345\274\217\345\256\236\344\276\213\345\214\226\350\247\243\345\206\263\346\250\241\346\235\277\345\210\206\346\226\207\344\273\266\351\227\256\351\242\230/main.cpp" "b/code/04\346\230\276\345\274\217\345\256\236\344\276\213\345\214\226\350\247\243\345\206\263\346\250\241\346\235\277\345\210\206\346\226\207\344\273\266\351\227\256\351\242\230/main.cpp" index b1d793a..1000426 100644 --- "a/code/04\346\230\276\345\274\217\345\256\236\344\276\213\345\214\226\350\247\243\345\206\263\346\250\241\346\235\277\345\210\206\346\226\207\344\273\266\351\227\256\351\242\230/main.cpp" +++ "b/code/04\346\230\276\345\274\217\345\256\236\344\276\213\345\214\226\350\247\243\345\206\263\346\250\241\346\235\277\345\210\206\346\226\207\344\273\266\351\227\256\351\242\230/main.cpp" @@ -17,6 +17,6 @@ int main() { x3.f(); x3.f2(); - // 类模板分文件 我们写了两个类模板 X X2,他们一个使用了成员函数显式实例化,一个类模板显式实例化,进行对比 + // 类模板分文件 我们写了两个类模板 X X2,它们一个使用了成员函数显式实例化,一个类模板显式实例化,进行对比 // 这主要在于我们所谓的类模板分文件,其实类模板定义还是在头文件中,只不过成员函数定义在 cpp 罢了。 } \ No newline at end of file diff --git "a/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/01\345\207\275\346\225\260\346\250\241\346\235\277.md" "b/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/01\345\207\275\346\225\260\346\250\241\346\235\277.md" index bf357ac..434d4fb 100644 --- "a/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/01\345\207\275\346\225\260\346\250\241\346\235\277.md" +++ "b/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/01\345\207\275\346\225\260\346\250\241\346\235\277.md" @@ -305,7 +305,7 @@ auto max(const T& a, const T2& b) -> decltype(true ? a : b){ 这是 C++11 后置返回类型,它和我们之前用默认模板实参 `RT` 的区别只是稍微好看了一点吗? -不,**他们的返回类型是不一样的**,如果函数模板的形参是**类型相同** `true ? a : b` 表达式的类型是 **`const T&`**;如果是 `max(1, 2)` 调用,那么也就是 `const int&`;而前面的例子只是 `T` 即 `int`(前面都是用模板类型参数直接构造临时对象,而不是有实际对象,自然如此,比如 `T{}`)。 +不,**它们的返回类型是不一样的**,如果函数模板的形参是**类型相同** `true ? a : b` 表达式的类型是 **`const T&`**;如果是 `max(1, 2)` 调用,那么也就是 `const int&`;而前面的例子只是 `T` 即 `int`(前面都是用模板类型参数直接构造临时对象,而不是有实际对象,自然如此,比如 `T{}`)。 > 假设以 `max(1,1.0)` 调用,那么自然返回类型不是 `const T&` > @@ -327,9 +327,9 @@ decltype(auto) max(const auto& a, const auto& b) { 1. [返回类型推导](https://zh.cppreference.com/w/cpp/language/function#.E8.BF.94.E5.9B.9E.E7.B1.BB.E5.9E.8B.E6.8E.A8.E5.AF.BC)(也就是函数可以直接写 auto 或 decltype(auto) 做返回类型,而不是像 C++11 那样,只是后置返回类型。 -2. [`decltype(auto)`](https://zh.cppreference.com/w/cpp/language/auto) “*。如果返回类型没有使用 decltype(auto),那么推导遵循[模板实参推导](https://zh.cppreference.com/w/cpp/language/template_argument_deduction#.E5.85.B6.E4.BB.96.E8.AF.AD.E5.A2.83)的规则进行*”,我们上面的 `max` 示例如果不使用 decltype(auto),按照模板实参的推导规则,是不会有引用和 cv 限定的,就只能推导出返回 `T` 类型。 +2. [`decltype(auto)`](https://zh.cppreference.com/w/cpp/language/auto) “*如果返回类型没有使用 decltype(auto),那么推导遵循[模板实参推导](https://zh.cppreference.com/w/cpp/language/template_argument_deduction#.E5.85.B6.E4.BB.96.E8.AF.AD.E5.A2.83)的规则进行*”。我们上面的 `max` 示例如果不使用 decltype(auto),按照模板实参的推导规则,是不会有引用和 cv 限定的,就只能推导出返回 `T` 类型。 -> 大家需要注意后置返回类型和返回类型推导的区别,他们不是一种东西,后置返回类型虽然也是写的 `auto` ,但是它根本没推导,只是占位。 +> 大家需要注意后置返回类型和返回类型推导的区别,它们不是一种东西,后置返回类型虽然也是写的 `auto` ,但是它根本没推导,只是占位。 模板的默认实参无处不在,比如标准库的 [std::vector](https://zh.cppreference.com/w/cpp/container/vector),[std::string](https://zh.cppreference.com/w/cpp/string/basic_string),当然了,这些都是类模板,我们以后会讲到。 @@ -406,7 +406,7 @@ void sum(Args...args){} 模板中需要 typename 后跟三个点 Args,函数形参中需要用模板类型形参包后跟着三个点 再 args。 -**args 是函数形参包,Args 是类型形参包,他们的名字我们可以自定义。** +**args 是函数形参包,Args 是类型形参包,它们的名字我们可以自定义。** **args 里,就存储了我们传入的全部的参数,Args 中存储了我们传入的全部参数的类型。** @@ -435,7 +435,7 @@ sum 的 `Args...args` 被展开为 `const char * args0, int args1, double args2` `&args...` 中 `&args` 就是模式,在展开的时候,模式,也就是省略号前面的一整个表达式,会被不停的填入对象并添加 `&`,然后逗号分隔。直至形参包的元素被消耗完。 -那么根据这个,我们就能写出一些有意思的东西,比如一次性把他们打印出来: +那么根据这个,我们就能写出一些有意思的东西,比如一次性把它们打印出来: ```cpp template diff --git "a/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/04\346\250\241\346\235\277\345\205\250\347\211\271\345\214\226.md" "b/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/04\346\250\241\346\235\277\345\205\250\347\211\271\345\214\226.md" index caab12a..a3b9f0c 100644 --- "a/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/04\346\250\241\346\235\277\345\205\250\347\211\271\345\214\226.md" +++ "b/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/04\346\250\241\346\235\277\345\205\250\347\211\271\345\214\226.md" @@ -72,7 +72,7 @@ int main(){ 我们使用全特化,实现了一个 `is_void` 判断模板类型实参是不是 `void` 类型。 -虽然很简单,但我们还是稍微强调一下:同一个类模板实例化的不同的类,彼此之间毫无关系,而静态数据成员是属于类的,而不是模板类;模板类实例化的不同的类,他们的静态数据成员不是同一个,请注意。 +虽然很简单,但我们还是稍微强调一下:同一个类模板实例化的不同的类,彼此之间毫无关系,而静态数据成员是属于类的,而不是模板类;模板类实例化的不同的类,它们的静态数据成员不是同一个,请注意。 --- diff --git "a/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/05\346\250\241\346\235\277\345\201\217\347\211\271\345\214\226.md" "b/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/05\346\250\241\346\235\277\345\201\217\347\211\271\345\214\226.md" index 4a284c2..ae3915c 100644 --- "a/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/05\346\250\241\346\235\277\345\201\217\347\211\271\345\214\226.md" +++ "b/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/05\346\250\241\346\235\277\345\201\217\347\211\271\345\214\226.md" @@ -4,7 +4,7 @@ 模板偏特化这个语法让**模板实参具有一些相同特征**可以自定义,而不是像全特化那样,必须是**具体的**什么类型,什么值。 -比如:指针类型,这是一类类型,有 `int*`、`double*`、`char*`,以及自定义类型的指针等等,他们都属于指针这一类类型;可以使用偏特化对指针这一类类型进行定制。 +比如:指针类型,这是一类类型,有 `int*`、`double*`、`char*`,以及自定义类型的指针等等,它们都属于指针这一类类型;可以使用偏特化对指针这一类类型进行定制。 - ***模板偏特化使我们可以对具有相同的一类特征的类模板、变量模板进行定制行为。*** diff --git "a/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/06\346\250\241\346\235\277\346\230\276\345\274\217\345\256\236\344\276\213\345\214\226\350\247\243\345\206\263\346\250\241\346\235\277\345\210\206\346\226\207\344\273\266\351\227\256\351\242\230.md" "b/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/06\346\250\241\346\235\277\346\230\276\345\274\217\345\256\236\344\276\213\345\214\226\350\247\243\345\206\263\346\250\241\346\235\277\345\210\206\346\226\207\344\273\266\351\227\256\351\242\230.md" index d835bcf..e45795c 100644 --- "a/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/06\346\250\241\346\235\277\346\230\276\345\274\217\345\256\236\344\276\213\345\214\226\350\247\243\345\206\263\346\250\241\346\235\277\345\210\206\346\226\207\344\273\266\351\227\256\351\242\230.md" +++ "b/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/06\346\250\241\346\235\277\346\230\276\345\274\217\345\256\236\344\276\213\345\214\226\350\247\243\345\206\263\346\250\241\346\235\277\345\210\206\346\226\207\344\273\266\351\227\256\351\242\230.md" @@ -78,7 +78,7 @@ int main() { x3.f(); x3.f2(); - // 类模板分文件 我们写了两个类模板 X X2,他们一个使用了成员函数显式实例化,一个类模板显式实例化,进行对比 + // 类模板分文件 我们写了两个类模板 X X2,它们一个使用了成员函数显式实例化,一个类模板显式实例化,进行对比 // 这主要在于我们所谓的类模板分文件,其实类模板定义还是在头文件中,只不过成员函数定义在 cpp 罢了。 } ``` diff --git "a/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/08\346\212\230\345\217\240\350\241\250\350\276\276\345\274\217.md" "b/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/08\346\212\230\345\217\240\350\241\250\350\276\276\345\274\217.md" index 0684262..84cb85b 100644 --- "a/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/08\346\212\230\345\217\240\350\241\250\350\276\276\345\274\217.md" +++ "b/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/08\346\212\230\345\217\240\350\241\250\350\276\276\345\274\217.md" @@ -112,7 +112,7 @@ int main(){ } ``` -这个示例很好,那么简单总结一下:左折叠和右折叠是需要注意的,他们的效果可能不同。 +这个示例很好,那么简单总结一下:左折叠和右折叠是需要注意的,它们的效果可能不同。 其实按照以上示例效果 `(4-(5-6))` `((4-5)-6)` 还可以总结一段简单的话:***右折叠就是先算右边,左折叠就是先算左边***。 diff --git "a/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/10\344\272\206\350\247\243\344\270\216\345\210\251\347\224\250SFINAE.md" "b/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/10\344\272\206\350\247\243\344\270\216\345\210\251\347\224\250SFINAE.md" index 110e98d..1a74a4e 100644 --- "a/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/10\344\272\206\350\247\243\344\270\216\345\210\251\347\224\250SFINAE.md" +++ "b/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/10\344\272\206\350\247\243\344\270\216\345\210\251\347\224\250SFINAE.md" @@ -57,7 +57,7 @@ int main(){ 以上的示例很好的向我们展示了 SFINAE 的作用,可以影响重载决议。 -`foo>(1)`、`foo(1)` 如果根据一般直觉,他们都会选择到 `void foo(int)`,然而实际却不是如此; +`foo>(1)`、`foo(1)` 如果根据一般直觉,它们都会选择到 `void foo(int)`,然而实际却不是如此; 这是因为 `foo(1);` 去尝试匹配 `void foo(int)` 的时候,模板实参类型 `void` 进行替换,就会变成: diff --git "a/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/11\347\272\246\346\235\237\344\270\216\346\246\202\345\277\265.md" "b/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/11\347\272\246\346\235\237\344\270\216\346\246\202\345\277\265.md" index 897b381..e9fa5d2 100644 --- "a/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/11\347\272\246\346\235\237\344\270\216\346\246\202\345\277\265.md" +++ "b/md/\347\254\254\344\270\200\351\203\250\345\210\206-\345\237\272\347\241\200\347\237\245\350\257\206/11\347\272\246\346\235\237\344\270\216\346\246\202\345\277\265.md" @@ -211,7 +211,7 @@ void f(T){} ## 约束 -前面我们讲的都是非常基础的*概念*(concept)使用,他们的约束也都十分简单,本节我们详细讲一下。 +前面我们讲的都是非常基础的*概念*(concept)使用,它们的约束也都十分简单,本节我们详细讲一下。 约束是逻辑操作和操作数的序列,它指定了对模板实参的要求。它们可以在 requires 表达式(见下文)中出现,也可以直接作为概念的主体。 @@ -582,7 +582,7 @@ int main() { - `requires` 表达式 -如果你耐心看完,我相信也能意识到他们是互相掺杂,一起使用的。语法上虽然感觉有些多,但是也都很合理,我们只需要 ***带入***,按照基本的常识判断这是不是符合语法,基本上就可以了。 +如果你耐心看完,我相信也能意识到它们是互相掺杂,一起使用的。语法上虽然感觉有些多,但是也都很合理,我们只需要 ***带入***,按照基本的常识判断这是不是符合语法,基本上就可以了。 `requires` 关键字的用法很多,但是划分的话其实就两类