Ответ 1
Проблема заключается в следующем: мы имеем 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)) );
За исключением того, что все эти get
неудобны и избыточны в лучшем случае, подвержены ошибкам в худшем случае. Теперь предположим, что у нас был тип index_sequence<0, 1, 2>
. Мы могли бы использовать это, чтобы свернуть эту инициализацию массива в расширение вариационного пакета:
template <typename Tuple, size_t... Indices>
std::array<int, sizeof...(Indices)>
call_f_detail(Tuple& tuple, 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))
. Это именно то, что мы хотим.
Последняя деталь проблемы - это просто генерация определенной последовательности индексов. С++ 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 answer:
template<typename T>
using Bare = typename std::remove_cv<typename std::remove_reference<T>::type>::type;