[英]Iterating through parameters of a variadic function template using variadic lambda
假设我们有以下函数模板:
template <typename Functor, typename... Arguments>
void IterateThrough(Functor functor, Arguments&&... arguments)
{
// apply functor to all arguments
}
此功能通常如下实现:
template <typename Functor, typename... Arguments>
void IterateThrough1(Functor functor, Arguments&&... arguments)
{
int iterate[]{0, (functor(std::forward<Arguments>(arguments)), void(), 0)...};
static_cast<void>(iterate);
}
其他方式:
struct Iterate
{
template <typename... Arguments>
Iterate(Arguments&&... arguments)
{
}
};
template <typename Functor, typename... Arguments>
void IterateThrough2(Functor functor, Arguments&&... arguments)
{
Iterate{(functor(std::forward<Arguments>(arguments)), void(), 0)...};
}
我找到了另一种使用可变参数lambda的方法:
template <typename Functor, typename... Arguments>
void IterateThrough3(Functor functor, Arguments&&... arguments)
{
[](...){}((functor(std::forward<Arguments>(arguments)), void(), 0)...);
}
与前两个相比,这种方法有哪些优点和缺点?
对functor
的调用现在还没有排序。 编译器可以按照所需的任何顺序使用扩展的参数调用functor
。 例如, IterateThrough3(functor, 1, 2)
可以做IterateThrough3(functor, 1, 2)
functor(1); functor(2);
functor(1); functor(2);
或者它可以做functor(2); functor(1);
functor(2); functor(1);
而另外两个总是做functor(1); functor(2);
functor(1); functor(2);
。
该标准的第8.5.4 / 4节要求{}
初始化程序内的任何表达式都是从左到右进行计算。
在braced-init-list的initializer-list中,initializer-clauses(包括pack扩展(14.5.3)产生的任何结果)按照它们出现的顺序进行评估。
第5.2.2 / 4节规定可以按任何顺序评估函数调用的参数。
调用函数时,应使用相应的参数初始化每个参数(8.3.5)(8.5,12.8,12.1)。 [注意:这种初始化相对于彼此不确定地排序(1.9) - 结束注释]
这可能不包括评估顺序的措辞(我找不到ATM),但众所周知,函数的参数是以未指定的顺序进行评估的。 编辑:请参阅@ dyp对相关标准报价的评论。
当你使用variadic lambda时,参数的评估顺序是根据语言规范而未指定的(这反过来意味着functor(argument)
的评估可以是程序员不知道的任何顺序)。 这是唯一的区别。 您可以在此站点上搜索“参数评估顺序”,您将看到许多主题。
至于可变参数模板化构造方法,只要你使用list-initialization来调用它就应该工作,否则它会和lambda有同样的问题。 请注意,GCC(高达4.8.2)有错误,所以这不起作用,但我不知道它是否与最新版本的GCC一起修复。
如果您的目标是使用没有外部机器的单线程,则可以使用接受std::initializer_list
的lambda:
template <typename Functor, typename... Arguments>
void IterateThrough3(Functor functor, Arguments&&... arguments)
{
[](std::initializer_list<int>){}(
{((void)functor(std::forward<Arguments>(arguments)), 0)...}
);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.