形参包及展开

最近在写IOU的时候想模仿上交的写法用形参包写一个可以接受不限参数的max或者min,但是真写起来坑太多了

形参包是c++11引入的语法,当使用形参包作为函数的形参时,可以传入不限个数以及类型的(0-....)参数。实质上形参包展开后就是使用逗号隔开的多个形参。

template <class T, class... Tp>
T reduce_max(T firstarg, Tp... args)
{
        return max(firstarg, reduce_max(args...));
}

这里的参数class ...Tp就是一个模板形参包类型的声明格式。注意当形参包作为参数时只能写在最后一个位置上。
作为类型时使用Tp... 参数名作为形参包类型的声明。
对应有几个操作。

template<class ...Tp>
size_t get_len(Tp ... args)
{
	cout << sizeof...(Tp) << endl;
	cout << sizeof...(args) << endl;
}

使用sizeof...运算符返回形参包的一些性质,前者返回类型个数,后者返回参数个数

形参包展开是指将打包的形参包展开为 int a, int c, int b, float d的形式,即展开为用逗号隔开的形参的形式

以上面的函数的为例,当传入

reduce_max(1,5,3,6,7)

时,其递归过程如下,我们不妨用中括号扩出形参包内的参数(不符合语法)

reduce(1, [5,3,6,7])
reduce(5,[3,6,7])
reduce(3,[6,7])
reduce(6,[7])
reduce(7,?) --5
reduce(?, ?)
.....

显然在最后一次递归时传入一个长度为0的形参包,这是没有意义的,而且如果不给出递归出口会导致无限递归。

解决的一种方法是再给出一个仅接受一个参数的重载

template <class T>
T reduce_max(T firstarg)
{
        return firstarg;
}

这样当递归到第五步时会调用这个重载,从而终止递归。
亦或这像这样写(从上交那里学来的)

template <class T, class... Tp>
T reduce_max(T firstarg, Tp... args)
{
    if constexpr (sizeof...(args) <= 0)
        return firstarg;
    else
        return max(firstarg, reduce_max(args...));
}

使用constexpr让if后的表达式在编译期确定范围,从而为其创造静态的递归出口。
如果不加constexpr的话连编译期都过不了

posted @ 2024-06-09 22:35  凪风sama  阅读(18)  评论(0编辑  收藏  举报