模板参数迭代

Posted

技术标签:

【中文标题】模板参数迭代【英文标题】:Template Parameter iteration 【发布时间】:2020-09-07 23:28:27 【问题描述】:

试图找到一种更简单的方法来遍历一组可变参数模板参数。

我的类包含一个由可变参数模板参数表示的对象元组。我想对元组的所有成员执行一个通用操作并返回一个聚合结果。

一个简化的例子是:

template<typename... Args>
struct Holder

    std::tuple<Args>    data;

    std::size_t getSize() const
    
        return getSizeData(std::make_index_sequence<sizeof...(Args)>());
    
    private:
       template<std::size_t... I>
       std::size_t getSizeData(std::index_sequence<I...>)
       
           // Initialize
           std::size_t result = 0;

           // Fold expression to iterate across all members in tuple.
           ((result += std::get<I>(data).getSize()), ...);

           // Aggregated value returned.
           return result;
       
;

这里对getSize() 的调用必须委派getSizeData() 的工作才能执行fold expression 需要命中元组的所有成员。

我已经避免使用std::get&lt;Kind&gt;(data).getSize(),因为这会限制元组存储每种类型中的一种(除非我在某种程度上弄错了)。

有没有更简单的方法来表达这一点而无需使用额外的功能。 IE。在getSize() 中完成所有工作,而不是将工作委托给getSizeData()

【问题讨论】:

我认为没有辅助函数是不可能的。你能用c++17吗?然后你可以在一行中使用std::apply @cigien 在提出问题之前尝试了几个小时。我一问问题就找到std::apply()。我不应该将 C++11 卡在标签中。是的,我可以在 C++11 之后使用任何东西。如果你回答我会接受你的回答。 好的,Args 中的每个类型都应该有一个getSize 成员函数吗?在这段代码中std::get&lt;I&gt;(data).getSize() 我的意思是? @cigien:是的;所有Args 都支持相同的“Duck”类型接口。我做了这个简化的例子getSize() 【参考方案1】:

您可以使用std::apply,它将元组解包到一个参数包中,让您编写一个折叠表达式,如下所示:

std::size_t getSize() const

    return std::apply([](auto... a) 
        return (a.getSize() + ...);
    , data);

这是demo。

【讨论】:

以上是关于模板参数迭代的主要内容,如果未能解决你的问题,请参考以下文章

如何确保函数模板的参数是随机访问迭代器?

为啥列表迭代器在 SGI STLs 实现中具有三个模板参数?

如何遍历打包的可变参数模板参数列表?

模板参数推导

是否可以在Azure ARM模板中执行迭代字符串替换?

C++11新特性从using化名模板到模板模板参数