如何按索引从可变参数模板参数包中提取值?

Posted

技术标签:

【中文标题】如何按索引从可变参数模板参数包中提取值?【英文标题】:How to extract a value from a variadic template parameter pack by index? 【发布时间】:2014-07-12 06:40:44 【问题描述】:

我想写一个函数magic_get,可以通过索引从参数包中提取一个值,例如:

int n = 0;
n = magic_get<0>(1, 3, 5, 7);
assert(1 == n);
n = magic_get<1>(1, 3, 5, 7);
assert(3 == n);
n = magic_get<2>(1, 3, 5, 7);
assert(5 == n);
n = magic_get<3>(1, 3, 5, 7);
assert(7 == n);

magic_get如何实现?

【问题讨论】:

【参考方案1】:
template <size_t N, typename... Args>
decltype(auto) magic_get(Args&&... as) noexcept 
    return std::get<N>(std::forward_as_tuple(std::forward<Args>(as)...));

如果 C++14 功能不可用,请将 decltype(auto) 更改为 auto 并添加尾随返回类型 decltype(/* the whole returned expression here */)


无元组版本:

template <std::size_t N, typename Tfirst, typename... Args, std::enable_if_t<N == 0, int>...>
decltype(auto) magic_get(Tfirst&& first, Args&&... as) noexcept 
    return std::forward<Tfirst>(first);


template <std::size_t N, typename Tfirst, typename... Args, std::enable_if_t<N != 0, int>...>
decltype(auto) magic_get(Tfirst&& first, Args&&... as) noexcept 
    return magic_get<N - 1>(std::forward<Args>(as)...);

请注意,这在 clang 中不起作用,感谢 clang bug 11723。用std::enable_if_t&lt;N != 0, int&gt; = 0 替换std::enable_if_t&lt;N != 0, int&gt;... 是一种简单的解决方法。

【讨论】:

是否可以避免构造元组对象? @xmllmx 是的,这是可能的,但为什么要重新发明***呢?优化器将优化所有内容,因为元组是引用元组,因此它的析构函数是微不足道的。

以上是关于如何按索引从可变参数模板参数包中提取值?的主要内容,如果未能解决你的问题,请参考以下文章

如何通过可变参数模板将多个构造函数参数转发到数组初始值设定项列表?

第4章 可变参数模板:4.2 折叠表达式

如何将构造函数(可变参数)作为模板参数传递?

如何将元组扩展为可变参数模板函数的参数?

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

C++ Primer 5th笔记(chap 16 模板和泛型编程)可变参数模板举例