首页 > 其他分享 >template<typename... T> 可变模板参数

template<typename... T> 可变模板参数

时间:2023-04-26 17:23:42浏览次数:38  
标签:... args Ts 参数 template 可变 模板

cppreference解释地址。

模板参数包在模板参数中的顺序要求:

在主类模板中,模板参数包必须是模板参数列表中的最后一个参数。
在函数模板中,模板参数包可能出现在列表的前面,前提是以下所有参数都可以从函数参数中推导出来,或者具有默认参数:

template < typename U, typename ... Ts >     // OK: 可以推断 U 
struct valid ; 
// template<typename... Ts, typename U> // 错误:Ts... 不在最后
// struct Invalid; 
 
template < typename ... Ts , typename U, typename = void > 
void valid ( U, Ts... ) ;     // OK:可以推导出 U 
// void valid(Ts..., U); // 不能使用:Ts... 是这个位置的非推导上下文
 
valid ( 1.0 , 1, 2 , 3 ) ;      // OK:将 U 推导为 double,将 Ts 推导为 {int, int, int}

pack expansion模板参数包扩展

情况一:参数包作为参数传入另一个带有可变模板参数的模板中

被扩展为零个或多个以逗号分隔的模式实例,其中参数包的名称从包中按顺序被每个元素替换

template<class... Us>
void f(Us... pargs) {}
 
template<class... Ts>
void g(Ts... args)
{
    f(&args...); // “&args...” is a pack expansion
                 // “&args” is its pattern
}
 
g(1, 0.2, "a"); // Ts... args expand to int E1, double E2, const char* E3
                // &args... expands to &E1, &E2, &E3
                // Us... pargs expand to int* E1, double* E2, const char** E3

情况二:如果两个参数包的名称以相同的模式出现,则它们被同时扩展,并且它们必须具有相同的长度:

template<typename...>
struct Tuple {};
 
template<typename T1, typename T2>
struct Pair {};
 
template<class... Args1>
struct zip
{
    template<class... Args2>
    struct with
    {
        typedef Tuple<Pair<Args1, Args2>...> type;
        // Pair<Args1, Args2>... is the pack expansion
        // Pair<Args1, Args2> is the pattern
    };
};
 
typedef zip<short, int>::with<unsigned short, unsigned>::type T1;
// Pair<Args1, Args2>... expands to
// Pair<short, unsigned short>, Pair<int, unsigned int> 
// T1 is Tuple<Pair<short, unsigned short>, Pair<int, unsigned>>
 
// typedef zip<short>::with<unsigned short, unsigned>::type T2;
// error: pack expansion contains parameter packs of different lengths

情况三:如果包扩展嵌套在另一个包扩展中

则出现在最里面的包扩展中的参数包由它扩展,并且必须在封闭的包扩展中提到另一个包,但不在最里面的包中:

template < class ... Args > 
void g ( Args ... args ) 
{ 
    f ( const_cast < const Args * > ( & args ) ... ) ;  
    // const_cast<const Args*>(&args) 是模式,它同时扩展两个包 // (Args 和 args)
  
    f ( h ( args... )  + args... ) ;  // 嵌套包扩展:
    // 内包扩展是“args...”,它首先被扩展
    // outer pack expansion is h(E1, E2, E3) + args..., 它被扩展
    // second (as h(E1, E2, E3) + E1, h(E1, E2, E3) + E2, h(E1, E2, E3) + E3) 
}

在完美转发时也会用到该模板参数包:同时扩展类型和实参

template<typename... ParamT>
f(ParamT... param){
  f2(std::forward<ParamT>(param)...);
}

扩展位点

参考cppreference

  • 函数参数列表
  • 带括号的初始值设定项
  • 模板参数列表
  • Lambda 捕获
  • sizeof...运算符
  • 动态异常规范
  • ....

标签:...,args,Ts,参数,template,可变,模板
From: https://www.cnblogs.com/xiaohuidi/p/17356621.html

相关文章

  • 洛谷 P3374——树状数组 / 树状数组模板题
    洛谷P3374——树状数组#include<iostream>usingnamespacestd;constintN=5e5+10;inttr[N],a[N];intn,m;intlowbit(intx){returnx&-x;}voidadd(intu,intc){//给所有管辖中有a[i]的tr[]加上cfor(inti=u;i<=n;i+......
  • makefile 通用模板
    ##Makefile##⭐全速编译命令:makeclean&&make-j$(nproc)#:=就地解析赋值=最后一次赋值?=未赋值时赋值+=接续赋值#mount-tnfs-onolock,vers=3192.168.5.12:/home/book/nfs_rootfs/mnt&&ps-ef|grepjc|grep-vgrep|awk'{print$1}'|xa......
  • template
    templatedemos(......
  • html模板
    <html><head><metacharset="utf-8"><title>菜鸟教程(runoob.com)</title></head><body><h1>我的第一个标题</h1><p>我的第一个段落。</p></body></html>```......
  • 4/25 cpp模板
    template<classT>classmyarr{intcapacity;intsize;T*arr;public:myarr(inta){arr=newT[a];size=0;capacity=a;}myarr(myarr<T>&a){arr=newT[a.capacity];......
  • 高精度模板 大数减大数 可变数组vector实现
    vector<int>Sub(vector<int>&A,vector<int>&B)//这里默认长数减去短数{vector<int>C;//结果向量intT=0;//上一位借位标志位for(inti=0;i<A.size();i++){T=A[i]-T;if(i<B.size())T-=B[i];//检......
  • 高精度模板 整数大数除以小整数数
    vector<int>Div(vector<int>&A,int&B){vector<int>C;intT=0;//除数for(inti=A.size()-1;i>=0;i--)//注意,除法模拟是从最高位开始的{T=T*10+A[i];//更新除数C.push_back(T/B);T%=B;......
  • 模板与群体数据2
    #include<iostream>#include<cstdlib>usingnamespacestd;structStudent{ intid; floatgpa;};template<classT>classStore{ private: Titem; boolhaveValue; public: Store(); T&getElem(); voidputElem(constT&x);}; templ......
  • 模板与群体数据1
    #include<iostream>usingnamespacestd;template<classT>voidoutputArray(constT*array,intcount){ for(inti=0;i<count;i++) cout<<array[i]<<""; cout<<endl;}intmain(){ constintA_COUNT=8,B_COUNT=8,C_COUNT=20; i......
  • CBV源码剖析和模板层
    getattr()函数用来返回函数的一个对象属性值语法:getattr(object,name,default)object--对象。name--字符串,对象属性。default--默认返回值,如果不提供该参数,在没有对应属性时,将触发AttributeError。>>>classA(object):...bar=1...>>>a=A()>>>getatt......