有人可以解释一下“指数技巧”吗?

Posted

技术标签:

【中文标题】有人可以解释一下“指数技巧”吗?【英文标题】:Can someone please explain the "indices trick"? 【发布时间】:2015-10-06 10:34:47 【问题描述】:

我注意到在漂亮打印元组的上下文中提到了“索引技巧”。听起来很有趣,所以我关注了the link。

好吧,那并不顺利。我理解这个问题,但真的无法理解发生了什么。为什么我们甚至需要任何东西的索引?那里定义的不同功能对我们有何帮助?什么是“裸”?等等

有人可以为参数包和可变元组方面的专家提供该内容的详细介绍吗?

【问题讨论】:

【参考方案1】:

问题是:我们有一个std::tuple<T1, T2, ...>,我们有一些函数f可以调用每个元素,其中f返回一个int,我们希望将这些结果存储在一个数组中.

让我们从一个具体的案例开始:

template <typename T> int f(T )  return sizeof(T); 

std::tuple<int, char, double> tup42, 'x', 3.14;
std::array<int, 3> arr f(std::get<0>(tup)), 
                        f(std::get<1>(tup)),
                        f(std::get<2>(tup)) );

除了写出所有这些gets 之外,充其量是不方便和多余的,最坏的情况是容易出错。

首先我们需要包含std::index_sequencestd::make_index_sequence 的实用程序标头:

#include <utility>

现在,假设我们有一个类型 index_sequence&lt;0, 1, 2&gt;。我们可以使用它来将该数组初始化折叠为可变参数包扩展:

template <typename Tuple, size_t... Indices>
std::array<int, sizeof...(Indices)> 
call_f_detail(Tuple& tuple, std::index_sequence<Indices...> ) 
    return  f(std::get<Indices>(tuple))... ;

这是因为在函数中,f(std::get&lt;Indices&gt;(tuple))... 被扩展为 f(std::get&lt;0&gt;(tuple)), f(std::get&lt;1&gt;(tuple)), f(std::get&lt;2&gt;(tuple))。这正是我们想要的。

问题的最后一个细节就是生成特定的索引序列。 C++14 实际上给了我们这样一个名为make_index_sequence的实用程序

template <typename Tuple>
std::array<int, std::tuple_size<Tuple>::value>
call_f(Tuple& tuple) 
    return call_f_detail(tuple,
        // make the sequence type sequence<0, 1, 2, ..., N-1>
        std::make_index_sequence<std::tuple_size<Tuple>::value>
        );

而您链接的文章只是解释了如何实现这样的元功能。

Bare 可能类似于来自Luc Danton's answer:

template<typename T>
using Bare = typename std::remove_cv<typename std::remove_reference<T>::type>::type;

【讨论】:

Bare 似乎类似于remove_reference_t。请注意,OP 链接页面上的代码通过转发引用获取元组,因此Tuple 可以是引用类型,而tuple_size 不适用于引用类型。 (从技术上讲,不需要remove_cvtuple_size 应该可以在 cv-qualified tuples 上正常工作。) 很好的答案,像往常一样。我在this answer 中找到了Bare 的可能定义,它似乎类似于decay_t 在call_f_detail的定义中,你的意思不是f(std::get&lt;Indices&gt;(tuple)...)而不是f(std::get&lt;Indices&gt;(tuple))...吗? 另外,还有一个更重要的问题——为什么我们需要灵活地“支持”任何索引序列?索引 不是包含不必要的冗余吗? @einpoklum 不,我没有。包扩展通过将表达式置于... 的左侧来工作,因此第一个表达式应为f(std::get&lt;0&gt;(tuple), std::get&lt;1&gt;(tuple), ...) 而不是f(std::get&lt;0&gt;(tuple)), f(std::get&lt;1&gt;(tuple)), ...。我们想对每个元素单独调用f,而不是对所有元素一起调用。请参阅 my answer here 了解扩展不同的包表达式

以上是关于有人可以解释一下“指数技巧”吗?的主要内容,如果未能解决你的问题,请参考以下文章

java中的数据源是啥?有人可以用简单的语言解释一下吗?

有人可以解释一下attr吗?

有人可以向我解释一下:'create(email: emailArg = ) '吗?

有人可以解释一下这个简单的python代码吗?

有人可以解释一下啥是受保护的覆盖无效吗? [复制]

有人可以为我解释一下这个 SQL 吗?