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

ein*_*ica 14 c++ tuples indices variadic-templates c++11

我注意到在精美打印元组的上下文中提到了"索引技巧".这听起来很有趣,所以我按照链接.

嗯,那不顺利.我理解了这个问题,但实际上并不能跟踪发生的事情.为什么我们甚至需要任何指数?那里定义的不同功能如何帮助我们?什么是'裸露'?等等

有人可以为参数包和可变元组的专家提供那种东西的游戏吗?

Bar*_*rry 17

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

让我们从具体案例开始:

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

std::tuple<int, char, double> tup{42, 'x', 3.14};
std::array<int, 3> arr{ f(std::get<0>(tup)), 
                        f(std::get<1>(tup)),
                        f(std::get<2>(tup)) );
Run Code Online (Sandbox Code Playgroud)

除了写出所有这些get都是不方便和冗余,最坏的情况下容易出错.现在,让我们说我们有一个类型std::index_sequence.我们可以使用它将该数组初始化折叠为可变参数包扩展:

#include <utility>
Run Code Online (Sandbox Code Playgroud)

那是因为在函数中,std::make_index_sequence扩展为index_sequence<0, 1, 2>.这正是我们想要的.

问题的最后一个细节就是生成特定的索引序列.C++ 14实际上给了我们这样一个名为的实用程序f(std::get<Indices>(tuple))...

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))... };
}
Run Code Online (Sandbox Code Playgroud)

而您链接的文章只是解释了如何实现这样的元函数.

f(std::get<0>(tuple)), f(std::get<1>(tuple)), f(std::get<2>(tuple))可能就像Luc Danton的回答一样:

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>{}
        );
}
Run Code Online (Sandbox Code Playgroud)

  • @einpoklum不,我没有.包扩展的工作方式是将表达式放在`...`的左边,所以第一个表达式会指向`f(std :: get <0>(tuple),std :: get <1>(元组), ...)`而不是`f(std :: get <0>(元组)),f(std :: get <1>(tuple)),...`.我们想要在每个元素上单独调用`f`,而不是在所有元素上调用`f`.有关扩展不同包表达式的信息,请参阅[我的答案](http://stackoverflow.com/a/26767333/2069064) (3认同)