精神文明网站建设内容互联网建造公司有哪些

当前位置: 首页 > news >正文

精神文明网站建设内容,互联网建造公司有哪些,网站制作商,手工外发货源怎么找目录 可变参数模板 1.1 概念 1.2 可变参数模板定义 1.3 参数包的展开方式 1.3.1 递归展开参数包 1.3.2 逗号表达式展开参数包 1.4 STL的emplace系列函数 可变参数模板 1.1 概念 在C语言阶段#xff0c;我们已经接触过可变参数#xff0c;比如scand、printf等等 这里…目录 可变参数模板 1.1 概念 1.2 可变参数模板定义 1.3 参数包的展开方式 1.3.1 递归展开参数包 1.3.2 逗号表达式展开参数包 1.4 STL的emplace系列函数 可变参数模板 1.1 概念 在C语言阶段我们已经接触过可变参数比如scand、printf等等 这里的 … 就是可变参数列表这也是 scanf 和 printf 可以接受多个参数的原因使用了可变参数列表但是scanf 和 printf 的可变参数是函数参数的可变参数并不是模板的可变参数 C11 的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板相比 C98/03类模版和函数模版中只能含固定数量的模版参数可变模版参数无疑是一个巨大的改进。但是由于可变模版参数比较抽象晦涩难懂使用起来需要一定的技巧 下面只讲解可变参数模板 1.2 可变参数模板定义 下面就是一个基本可变参数的函数模板 // Args是一个模板参数包args是一个函数形参参数包 // 声明一个参数包Args…args这个参数包中可以包含0到任意个模板参数。 template class …Args void ShowList(Args… args) {} 上面的参数 args 前面有省略号所以它就是一个可变模版参数我们把带省略号的参数称为 “参数包”它里面包含了0到NN0个模版参数。Args是一个模板参数包args是一个函数形参参数包我们无法直接获取参数包 args 中的每个参数的只能通过展开参数包的方式来获取参数包中的每个参数这是使用可变模版参数的一个主要特点也是最大的难点即如何展开可变模版参数。 可以在函数模板中通过 sizeof 计算参数包中参数的个数代码如下 注意sizeof 后面也需要加上参数列表 … 不加直接报错  templateclass …Args void ShowList(Args… args) {cout sizeof…(args) endl; //获取参数包中参数的个数 }int main() {ShowList(1);ShowList(1, 2);ShowList(11, 22, a);ShowList(11, 22, a, BBB);ShowList();return 0; } 运行结果 但是我们无法直接获取参数包中的每个参数只能通过展开参数包的方式来获取这是使用可变参数模板的一个主要特点也是最大的难点 因为语法不支持使用 args[i] 这样方式获取可变参数所以我们无法直接获取参数包中的每个参数 templateclass …Args void ShowList(Args… args) {//error语法不支持for (int i 0; i sizeof…(args); i){cout args[i] ; //打印参数包中的每个参数}cout endl; } 这样编译是无法通过的也不知道当时的大佬为什么不这样设计这样设计很方便理解可变参数列表 1.3 参数包的展开方式 参数包的展开方式有递归展开参数包、使用逗号表达式展开参数包 1.3.1 递归展开参数包 递归展开参数包的方式如下 需要给函数模板增加一个模板参数T这样就可以从接收到的参数包中分离出一个参数出来参数包分离出的一个参数后给给新增加的模板参数T打印完了第一个参数后在函数模板中递归调用该函数模板调用时传入剩下的参数包这时又会从参数包中分离出一个参数给给另一个模板参数T如此递归下去每次分离出参数包中的一个参数直到参数包中的所有参数都被取出来为了终止递归需要对该模板函数进行重载重载一个新的模板函数参数只有一个T模板参数当参数包中的个数为1时调用函数就会去匹配我们重载的模板函数这样递归就可以终止了 注意这里的递归调用结束函数需要写成函数模板因为我们并不知道最后一个参数是什么类型的  测试代码 // 递归终止函数重载ShowList函数 template class T void ShowList(const T t) {cout t endl; } // 展开函数 template class T, class …Args void ShowList(T value, Args… args) {cout value ;ShowList(args…); } int main() {ShowList(1);ShowList(1, 2);ShowList(1, A);ShowList(1, A, std::string(sort));return 0; } 运行结果可以获取并打印参数包的每一个参数 当然也还可以重载以个无参的函数这时重载的函数就不用加模板了代码如下 // 递归终止函数重载ShowList函数 void ShowList() {cout endl; } // 展开函数 template class T, class …Args void ShowList(T value, Args… args) {cout value ;ShowList(args…);//将剩下参数包继续向下传 } int main() {ShowList(1);ShowList(1, 2);ShowList(1, A);ShowList(1, A, std::string(sort));return 0; } 注意这里是当参数包中的个数为0时调用函数就会去匹配我们重载的函数结束递归 运行结果可以获取并打印参数包的每一个参数 1.3.2 逗号表达式展开参数包 数组可以通过列表进行初始化比如: int a[] {1,2,3,4,5}; 如果参数包中各个参数的类型都是整型那么也可以把这个参数包放到列表当中初始化这个整型数组此时参数包中参数就放到数组中了例如 //展开函数 templateclass …Args void ShowList(Args… args) {int arr[] { args… }; //列表初始化//打印参数包中的各个参数for (auto e : arr){cout e ;}cout endl; }int main() {ShowList(1);ShowList(1, 2);ShowList(1, 2, 3);return 0; } 运行结果 C规定一个容器中存储的数据类型必须是相同的因此如果这样写的话那么调用 ShowList函数时传入的参数只能是整型的并且还不能传入0个参数因为数组的大小不能为0因此我们还需要在此基础上借助逗号表达式来展开参数包 逗号表达式展开参数包的方式不需要通过递归终止函数是直接在 展开函数体expand函数体中展开的 逗号表达式会从左到右依次计算各个表达式并且将最后一个表达式的值作为返回值进行返回。将逗号表达式的最后一个表达式设置为一个整型值确保逗号表达式返回的是一个整型值。将处理参数包中参数的动作封装成一个函数将该函数的调用作为逗号表达式的第一个表达式 这样一来在执行逗号表达式时就会先调用处理函数处理对应的参数然后再将逗号表达式中的最后一个整型值作为返回值来初始化整型数组 测试代码 template class T void PrintArg(T t) {cout t ; } //展开函数 template class …Args void ShowList(Args… args) {int arr[] { (PrintArg(args), 0)… };//列表初始化逗号表达式cout endl; } int main() {ShowList(1);ShowList(1, 1.1);ShowList(1, A);ShowList(1, A, std::string(sort));return 0; } 运行结果 解释  Printar函数不是一个递归终止函数只是一个处理参数包中每一个参数的函数。这种就地展开参数包的方式实现的关键是逗号表达式。expand函数中的逗号表达式(Printarg(args), 0)也是按照这个执行顺序先执行 Printarg(args)再得到逗号表达式的结果0同时还用到了 C11的另外一个特性——初始化列表通过初始化列表来初始化一个变长数组, {(Printarg(args), 0)…} 将会展开成 ((Printarg(arg1),0), (Printarg(arg2),0), (Printarg(arg3),0), etc… )最终会创建一个元素值都为0的数组 int arr[sizeof…(Args)]。由于是逗号表达式在创建数组的过程中会先执行逗号表达式前面的部分 Printarg(args) 打印出参数也就是说在构造int数组的过程中就将参数包展开了这个数组的目的纯粹是为了在数组构造的过程展开参数包 这时调用ShowList函数时就可以传入多个不同类型的参数了但调用时仍然不能传入0个参数因为数组的大小不能为0 如果想要支持传入0个参数也可以重载一个无参的 ShowList函数 //支持无参调用 void ShowList() {cout endl; } //处理函数 templateclass T void PrintArg(const T t) {cout t ; } //展开函数 templateclass …Args void ShowList(Args… args) {int arr[] { (PrintArg(args), 0)… }; //列表初始化逗号表达式cout endl; } int main() {ShowList();ShowList(1);ShowList(1, 1.1);ShowList(1, A);ShowList(1, A, std::string(sort));return 0; } 运行结果可以传入无参的 实际上我们也可以不用逗号表达式因为这里的问题就是初始化整型数组时必须用整数那我们可以将处理函数的返回值设置为整型然后用这个返回值去初始化整型数组也是可以的 代码如下 //处理函数 templateclass T int PrintArg(const T t) {cout t ;return 0; } //展开函数 templateclass …Args void ShowList(Args… args) {int arr[] { PrintArg(args)… }; //列表初始化cout endl; } int main() {ShowList();ShowList(1);ShowList(1, 1.1);ShowList(1, A);ShowList(1, A, std::string(sort));return 0; }1.4 STL的emplace系列函数 C11标准给STL中的容器增加emplace系列的插入接口 比如vector的push_back和 insert函数都增加了对应的 emplace_back和 emplace函数 list容器的 push_front、push_back和 insert函数都增加了对应的 emplace_front、emplace_back和 emplace函数 这些emplace版本的插入接口支持模板的可变参数和万能引用比如list的emplace函数 emplace系列接口的使用方式与容器原有的插入接口的使用方式类似但又有一些不同之处这个不解释了想知道自己可以进行查阅 —————-我是分割线————— 文章到这里就结束了下一篇即将更新