【发布时间】:2022-01-22 03:51:48
【问题描述】:
抱歉,我的问题含糊不清,但我只是不明白这个函数的作用和方式。来自here的代码:
template<typename ... T>
auto sum (T ... t)
{
typename std::common_type<T...>::type result{}; //zero-initialization?
(void)std::initializer_list<int>{(result += t, 0)...}; //why 0 is here
return result;
}
我不知道为什么,但是这段代码看起来很奇怪,在我看来它不像 C++。从语义上讲,这个函数显然将结果变量中的所有参数相加。但我完全不明白为什么要这样写。在此处使用 initializer_list 似乎是触发对参数包中的参数进行迭代的技巧,但仍然...
为什么 initializer_list 被明确地强制转换为 void?不占用额外内存?
参数包的迭代是如何进行的?为什么不呢,比如(void)std::initializer_list<int>{(result += t)...};(顺便说一下它不会编译)。
【问题讨论】:
-
在 C++17 发明 fold expressions 之前,这个技巧很常见。现在,你可以写
return (... + t);在此之前,包扩展只能出现在某些上下文中,例如在大括号初始化列表中。因此,要对包执行计算,您安排了一个虚拟大括号初始化列表,其中每个初始化程序都有您想要的副作用。初始化器的值无关紧要,只有它的副作用。(result += t, 0)使用逗号运算符 - 它表示“评估result += t,然后生成整数0作为值”。 -
强制转换为
void是为了避免某些编译器对未使用的表达式发出警告。 -
std::initializer_list<int>{(result += t)...};无法编译可能是因为(result += t)不是int类型或不能转换为int。相比之下,(result += t, 0)的类型始终是0的类型,即int。
标签: c++ variadic-templates variadic-functions