繁体   English   中英

使用可变参数lambda迭代可变参数函数模板的参数

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM