有人可以解释一下 "indices trick" 吗?
Can someone please explain the "indices trick"?
我注意到在漂亮的打印元组的上下文中提到了 "indices trick"。听起来很有趣,所以我关注了the link。
嗯,这并不顺利。我理解这个问题,但真的无法理解发生了什么。为什么我们甚至需要任何东西的索引?那里定义的不同功能如何帮助我们?什么是 'Bare'?等等
有人可以为参数包和可变元组方面的非专家详细介绍一下吗?
问题是:我们有一个 std::tuple<T1, T2, ...>
并且我们有一些可以在每个元素上调用的函数 f
,其中 f
returns 一个 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)) );
除了写出所有这些 get
是不方便和多余的,最坏的情况下容易出错。
首先,我们需要包含 std::index_sequence
和 std::make_index_sequence
的实用程序头文件:
#include <utility>
现在,假设我们有一个类型 index_sequence<0, 1, 2>
。我们可以使用它来将数组初始化折叠成可变包扩展:
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<Indices>(tuple))...
被扩展为 f(std::get<0>(tuple)), f(std::get<1>(tuple)), f(std::get<2>(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;
我注意到在漂亮的打印元组的上下文中提到了 "indices trick"。听起来很有趣,所以我关注了the link。
嗯,这并不顺利。我理解这个问题,但真的无法理解发生了什么。为什么我们甚至需要任何东西的索引?那里定义的不同功能如何帮助我们?什么是 'Bare'?等等
有人可以为参数包和可变元组方面的非专家详细介绍一下吗?
问题是:我们有一个 std::tuple<T1, T2, ...>
并且我们有一些可以在每个元素上调用的函数 f
,其中 f
returns 一个 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)) );
除了写出所有这些 get
是不方便和多余的,最坏的情况下容易出错。
首先,我们需要包含 std::index_sequence
和 std::make_index_sequence
的实用程序头文件:
#include <utility>
现在,假设我们有一个类型 index_sequence<0, 1, 2>
。我们可以使用它来将数组初始化折叠成可变包扩展:
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<Indices>(tuple))...
被扩展为 f(std::get<0>(tuple)), f(std::get<1>(tuple)), f(std::get<2>(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;