1.C++11-可变参数模板(Variadic Templates)

1.概述

可变参数模板(variadic template)是一个接收可变数目参数的模板函数或模板类。可变数目的参数被称为参数包(parameter packet)。存在两种参数包:模板参数包(template parameter packet),表示零个或多个模板参数;函数参数包(function parameter packet),表示零个或多个函数参数。

2.语法

用一个省略号指出一个模板参数或函数参数表示一个包。在一个模板参数列表中,class...typename...指出接下来的参数表示零个或多个类型的列表;一个类型名后面跟一个省略号表示零个或多个给定类型的非类型参数的列表。在函数参数列表中,如果一个参数的类型是一个模板参数包,则此参数也是一个函数参数包。例如:

	// Args是一个模板参数包;rest是一个函数参数包
	// Args表示零个或多个模板类型参数
	// rest表示零个或多个函数参数
    template<typename T, typename... Args>
    void foo(const T& t, const Args... rest);

上面声明了foo是一个可变参数函数模板,它有一个名为T的类型参数,和一个名为Args的模板参数包。这个包表示零个或多个额外的类型参数。foo的函数参数列表包含一个const&类型的参数,指向T的类型,还包含一个名为rest的函数参数包,此包表示零个或多个函数参数。
与往常一样,编译器从函数的实参推断模板参数类型。对于一个可变参数模板,编译器还会推断包中的参数数量。例如,给定下面的调用:

    int i = 0; double d = 3.14; string s = "how now brown cow";
    foo(i, s, 42, d);    // 包中有三个参数,i对应t,s 42 d属于参数包
    foo(s, 42, "hi");    // 包中有两个参数
    foo(d, s);           // 包中有一个参数
    foo("hi");           // 空包

编译器会为foo实例化出四个不同的版本:

    void foo(const int&, const string&, const int&, const double&);
    void foo(const string&, const int&, const char[3]&);
    void foo(const double&, const string&);
    void foo(const char[3]&);

在每个实例中,T的类型都是从第一个实参的类型中推断出来的,剩下的实参(如果有的话)提供函数额外实参的数目和类型。
当需要知道参数包中的参数数量时,可以使用sizeof...运算符。类似sizeofsizeof...也返回一个常量表达式,而且不会对其实参求值:

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

3.实例

    #include <iostream>
    #include <bitset>

    // 无参数时调用
    void print()
    {
        std::cout << "\nprint end!" << std::endl;
    }
    // 递归调用,当参数为0时调用上面的print函数
    template<typename T, typename... Types>
    void print(const T& firstArg, const Types&... args)
    {
        std::cout << firstArg  << ", ";
        print(args...);
    }


    template<typename... Types>
    void print_entry(const Types&... args)
    {
        // 打印参数类型数量和参数数量
        std::cout << "Types size: " << sizeof...(Types)
            << ", args size: " << sizeof...(args) << std::endl;
        print(args...);
    }

    int main(int argc, char* argv[])
    {
        print_entry(7.5, "hello", std::bitset<16>(377), 42);
        return 0;
    }

参考资料

  1. C++ Primer 第五版
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值