可变参数模板函数中std::initializer_list用法的技术疑问
拆解这个可变参数sum函数的运行原理,尤其是std::initializer_list的用法
咱们一步一步来拆解这段代码,搞清楚它到底在做什么,特别是你疑惑的std::initializer_list部分。
首先看完整的函数:
template<typename ... T> auto sum(T ... t) { typename std::common_type<T...>::type result{}; std::initializer_list<int>{ (result += t, 0) ... }; return result; }
1. 可变参数模板的基础
template<typename ... T>是C++的可变参数模板语法,T...表示一个参数包,可以接受任意数量、任意类型的参数(比如sum(1, 2.5, 3)这样的调用都是合法的)。auto作为返回值类型,会自动推导最终的返回类型。
2. 结果变量的类型初始化
typename std::common_type<T...>::type result{};这行做了两件事:
std::common_type<T...>是标准库工具,用来计算所有参数类型T...的共同类型——也就是能容纳所有参数值的最合适的类型。比如你传入int和double,共同类型就是double;传入多个int,就是int。result{}是值初始化,把result设为该类型的默认值(比如数值类型就是0,0.0之类的)。
3. 核心:用std::initializer_list触发参数包展开
这是你最疑惑的部分,咱们重点说:std::initializer_list<int>{ (result += t, 0) ... };
首先,...是参数包展开运算符,它会把参数包t...里的每个元素单独拿出来,重复执行前面的表达式。但问题是,C++里不能直接写(result += t)...——它需要一个能容纳展开结果的上下文,而std::initializer_list就是干这个的。
再看里面的逗号表达式(result += t, 0):
- 逗号表达式的规则是:先执行左边的
result += t(这会把当前参数t加到result上,完成累加操作),然后丢弃左边的结果,返回右边的0。 - 展开后,这个初始化列表会变成类似
{ (result += t1, 0), (result += t2, 0), (result += t3, 0), ... }的形式,每个元素都是0,但真正有用的是执行累加的副作用。
为什么要用std::initializer_list<int>?因为我们需要一个合法的结构来让参数包展开。初始化列表会强制编译器把每个参数对应的表达式都执行一遍,而我们并不关心初始化列表里的0是什么——只是利用它来触发展开、执行累加。
4. 返回最终结果
最后return result;就把累加完成的结果返回了。
举个实际调用的例子
比如调用sum(1, 2.5, 3),执行过程是:
std::common_type<int, double, int>::type是double,所以result初始化为0.0。- 初始化列表展开为
{ (result +=1,0), (result +=2.5,0), (result +=3,0) }:- 先执行
result +=1→result=1.0,返回0; - 再执行
result +=2.5→result=3.5,返回0; - 再执行
result +=3→result=6.5,返回0;
- 先执行
- 初始化列表被创建(但我们不会用到它),最后返回
6.5。
内容的提问来源于stack exchange,提问作者Mustafa COKER
相关产品推荐
相关产品推荐

