广东省住房城乡建设厅官方网站,网站建设注意问题,做网站开发哪里可以接单,关键词排名优化软件价格前言#xff1a;
在C语言中#xff0c;我们谈论了有关可变参数的相关知识。在C11中引入了一个新特性---即可变参数模板。本期#xff0c;我们将要介绍的就是有关可变参数模板的相关知识#xff01;#xff01;#xff01;
目录
序言
#xff08;一#xff09;可变参…前言
在C语言中我们谈论了有关可变参数的相关知识。在C11中引入了一个新特性---即可变参数模板。本期我们将要介绍的就是有关可变参数模板的相关知识
目录
序言
一可变参数模板函数
1、sizeof... 运算符
二扩展参数包的两种方法
1、递归函数方式展开参数包
2、逗号表达式展开参数包
3、两种方法的优缺点
总结 序言
C11的新特性可变参数模板能够让我们可以接受可变参数的函数模板和类模板相比 C98/03类模版和函数模版中只能含固定数量的模版参数可变模版参数无疑是一个巨大的改进。然而由于可变模版参数比较抽象使用起来需要一定的技巧所以这块还是比较晦涩的。现阶段呢我们掌握一些基础的可变参数模板特性就够我们用了所以这里我们点到为止以后大家如果有需要再可以深入学习。 一可变参数模板函数 在了解模板函数和模板类之前我们需要先知道几个概念 一个 可变参数模板 就是一个接收可变数目参数的模板函数或者是模板类。可变数目的参数被称为 函数包。存在两种函数包
模板参数包使用 typename/class ... Args 来指出 Args 是一个模板参数包表示零个或多个模板参数函数参数包使用 Args ... rest 来指出 rest 是一个函数参数包表示零个或多个函数参数 下面就是一个基本可变参数的函数模板
// Args是一个模板参数包args是一个函数形参参数包
// 声明一个参数包Args...args这个参数包中可以包含0到任意个模板参数。
template class ...Args
void ShowList(Args... args)
{}
【解释说明】
上面的参数args前面有省略号所以它就是一个可变模版参数我们把带省略号的参数称为“参数包”它里面包含了0到NN0个模版参数。 与往常一样编译器从函数的实参推倒模板参数类型。对于一个可变参数模型编译器还会推断包中参数的数目。例如看下面一个简单例子
// 可变参数函数模板
templatetypename... Args
void printArgs(Args... args)
{cout Number of arguments: sizeof...(args) endl;cout endl;
}int main() {printArgs(1, 2, 3); // 输出Number of arguments: 3 Arguments: 1 2 3printArgs(Hello, 3.14, c); // 输出Number of arguments: 3 Arguments: Hello 3.14 cprintArgs(10); // 输出Number of arguments: 1 Arguments: 10printArgs(); // 输出Number of arguments: 0 Arguments:return 0;
} 编译器会为 printArgs 实例化出以下四个不同版本我们看下上面程序的汇编代码 1、sizeof... 运算符 大家可以发现上述代码样例中我使用了 sizeof... 这样的字段。那么这个是什么意思呢 其实是 sizeof... C11引入的一元运算符用于获取可变模板参数包中的参数数量
因此接下来我尝试运行一下代码看结果 【解释说明】
在上面的示例中我们定义了一个函数模板 printArgs 它接受可变数量的模板参数。在函数模板中我们使用 sizeof... 来获取参数包 args 中的参数数量 【小结】 运算符可以用于类模板和函数模板中用于获取参数包的大小它在处理可变参数模板时非常有用可以帮助我们实现更加灵活和通用的代码。 二扩展参数包的两种方法 因为我们无法直接获取参数包args中的每个参数只能通过展开参数包的方式来获取参数包中的每个参数这是使用可变模版参数的一个主要特点也是最大的难点即如何展开可变模版参数。由于语法不支持使用args[i]这样方式获取可变参数所以我们的用一些奇招来一一获取参数包的值。 1、递归函数方式展开参数包
通过递归函数方式展开参数包是一种常见的处理可变参数模板的方法。这种方法利用函数的递归调用来依次处理参数包中的每个参数。
下面是一个示例展示了如何使用递归函数方式展开参数包
// 递归终止函数
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, A);ShowList(1, A, std::string(sort));return 0;
}
【解释说明】 在上面的示例中ShowList 是一个展开函数模板用于递归展开参数包并输出每个参数的值。 ShowList(const T t)是递归终止函数用于处理只有一个参数的情况。它接受一个参数 t并将其输出到标准输出流ShowList(T value, Args... args)是展开函数模板的递归部分。它接受一个参数 value 和更多的参数包 Args... args。在函数体内它首先输出 value 的值然后通过递归调用 ShowList 函数来处理剩余的参数包 args... 以下是运行上述代码的输出结果 通过递归函数方式展开了参数包并成功输出了每个参数的值。这是一种常见的使用递归的方法来处理可变参数模板的方式。 【注意】 当定义可变参数版本的 ShowList 时非可变参数版本必须要声明在可变参数版本 (递归体) 的作用域当中否则会导致无限递归 2、逗号表达式展开参数包 这种展开参数包的方式不需要通过递归终止函数是直接在expand函数体中展开的, printarg 不是一个递归终止函数只是一个处理参数包中每一个参数的函数。这种就地展开参数包的方式 实现的关键是逗号表达式。我们知道逗号表达式会按顺序执行逗号前面的表达式。
下面是一个示例展示了如何利用逗号表达式来展开参数包
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, A);ShowList(1, A, std::string(sort));return 0;
}
【解释说明】
在上面的示例中PrintArg 是一个简单的辅助函数模板用于打印参数的值。
ShowList 是一个展开函数模板它接受可变数量的参数并使用逗号表达式来展开参数包。在展开过程中每个参数都会被传递给 PrintArg 函数进行处理并且逗号表达式的结果被忽略。在 main 函数中我们调用了 ShowList 函数并传递了不同数量和类型的参数。通过逗号表达式展开参数包每个参数都会被依次处理并调用 PrintArg 函数将其值输出到标准输出流。
以下是运行上述代码的输出结果 上述代码我们还可以像下述这样去进行实现操作 【说明】 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数组的过程中就将参数包展开了这个数组的目的纯粹是为了在数组构造的过程展开参数包。 3、两种方法的优缺点 逗号表达式扩展方式和递归包扩展方式都可以用于展开可变参数模板但它们具有不同的优缺点 具体如下
逗号表达式扩展方式的优点
简洁性使用逗号表达式可以在一行代码中展开参数包代码量较少且结构清晰。高效性逗号表达式会在编译时展开参数包可以生成高效的代码。可读性逗号表达式展开参数包的语法较为直观易于阅读和理解。
逗号表达式扩展方式的缺点
顺序限制逗号表达式展开参数包的顺序是从左到右无法灵活地改变参数的处理顺序。局限性逗号表达式虽然简洁但在某些复杂的情况下可能比较难以处理。
递归包扩展方式的优点
灵活性利用递归函数方式展开参数包可以在每一步递归中对参数进行处理和逻辑操作具有更高的灵活性。可控性递归包展开方式可以通过递归函数中的控制语句和条件语句对参数包的展开进行控制。
递归包扩展方式的缺点
代码冗余递归函数方式展开参数包可能需要更多的代码量来实现相对于逗号表达式方式来说代码可能会更冗长。可读性递归函数方式展开参数包的代码结构可能比较复杂不够直观。
根据具体的情况和需求可以根据代码的复杂度和可读性的要求选择使用逗号表达式扩展方式或递归包扩展方式。逗号表达式方式适用于简单的参数展开而递归包方式则适用于复杂的参数展开可以更灵活地进行处理。 总结 以上便是关于c11 可变参数模板函数的全部知识讲解感谢大家的观看与支持