C++Primer_Chap16_模板和泛型编程_List04_可变参数模板_笔记

  一个可变参数模板(variable template)就是一个接受可变数目参数的模板函数或模板类。可变数目的参数被称为参数包(parameter packet)。存在两种参数宝:

  • 模板参数包(template parameter packet),表示0个或多个模板参数
  • 函数参数包(function parameter packet),表示0个或多个函数参数。

  我们用一个省略号来指出一个模板参数或函数参数表示一个包。

  • 在一个模板参数列表中,class... 或typename...指出接下来的参数表示0个或多个类型的列表;
  • 一个类型名后面跟...表示0个或多个给定类型的非类型参数的列表。
  • 在函数参数列表中,如果一个参数的类型是一个模板参数包,则此参数也是以个函数参数包
//Args是一个模板参数包;rest是一个函数参数包
//Args表示0个或多个模板类型参数
//rest表示0个或多个函数参数
template <typename T, typename... Args>
void foo(const T &t, const Args... rest);

  当我们需要知道包中有多少元素时,可以使用sizeof...运算符,sizeof...运算符也返回一个常量表达式,且不对实参求值:

template<typename ... Args> void g(Args ... args)
{
    cout << sizeof...(Args) << endl;    //类型参数的数目
    cout << sizeof...(args) << endl;    //函数参数的数目
}

编写可变参数函数模板

  我们可以使用一个initializer_list来定义一个可接受可变数目同种类型实参的函数。但实参类型不一致时,可变参数函数是很有用的。

  可变参数函数通常是递归的。第一步调用处理保重的第一个实参,然后用剩余参数调用自身,print函数每次递归调用将第二个参数打印到第一个实参表示的流中。为了终止递归,还定义一个非可变参数的print函数

template<typename T>
ostream &print( ostream &os, const T &t)
{
    return os << t;
}

template<typaname T, typename... Args>
ostream &print( ostream &os, const T &t, const Args&... rest)
{
    os << t << ", ";
    returen print(os, rest...);
}

  当定义可变参数版本的print时,非可变参数版本的声明必须出现在作用域中。否则,可变参数版本会无限递归。

包扩展

  对于一个参数包,除了获取其大小外,我们能做的唯一的事情就是扩展(expand)它。当扩展一个包时,我们还要提供用于每个扩展元素的模式(pattern)。扩张一个包就是将它分解成构成的元素,对每个元素应用模式,获得扩展后的列表。通过在模式右边放一个省略号(...)来触发扩展操作

template<typaname T, typename... Args>
ostream &
print( ostream &os, const T &t, const Args&... rest)    //扩展Args
{
    os << t << ", ";
    returen print(os, rest...);        //扩展rest
}


template <typename... Args>
ostream &
errorMsg(ostream &os, const Args&... rest)
{
    return print(os, debug_rep(rest)...);
}

  这个print调用使用了模式debug_rep(rest)。此模式表示我们希望对函数参数包rest中的每个元素调用debug_rep。扩展的结果将是一个逗号分隔的debug_rep调用列表。扩展中的模式会独立地应用于包中的每个元素。

转发参数包

  我们可以组合使用可变参数模板与forward机制来编写函数,实现将其实参不变地传递给其他函数。

class StrVec {
public:
    template <class... Args> void emplace_back(Args&&...);
};

template<class... Args>
inline
void StrVec::emplace_back(Args&&... args)
{
    check_n_alloc();
    alloc.construct(first_free++, std::forward<Args>(args)...);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值