Il problema è: abbiamo un std::tuple<T1, T2, ...>
e abbiamo qualche funzione f
che possiamo chiamare su ogni elemento, dove f
restituisce un int
, e vogliamo memorizzare i risultati in un array.
Cominciamo con un caso concreto:
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)));
Tranne scrivere tutte quelle get
s è scomodo e ridondante nella migliore delle ipotesi, soggetto a errori nel peggiore dei casi. Ora, diciamo che avevamo un tipo index_sequence<0, 1, 2>
. Potremmo usarlo per comprimere tale inizializzazione array in un pacchetto di espansione variadic:
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))... };
}
Questo perché all'interno della funzione, f(std::get<Indices>(tuple))...
viene espanso a f(std::get<0>(tuple)), f(std::get<1>(tuple)), f(std::get<2>(tuple))
. Che è esattamente quello che vogliamo
L'ultimo dettaglio del problema è solo la generazione di quella particolare sequenza di indici. C++ 14 in realtà ci dà una tale utility chiamata 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>{}
);
}
mentre l'articolo si è collegato semplicemente spiega come si potrebbe implementare tale metafunction.
Bare
è probabilmente qualcosa di simile, da Luc Danton's answer:
template<typename T>
using Bare = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
'Bare' sembra qualcosa lungo le linee di' remove_reference_t'. Si noti che il codice sulla pagina OP collegata prende la tupla inviando il riferimento, quindi 'Tuple' può essere un tipo di riferimento e' tuple_size' non funziona sui tipi di riferimento. (Tecnicamente, 'remove_cv' non è necessario.' Tuple_size' dovrebbe funzionare correttamente su 'tuple's cv-qualified.) –
Ottima risposta, come al solito. Ho trovato una possibile definizione di 'Bare' in [questa risposta] (http://stackoverflow.com/a/10615119/1274223), che sembra essere qualcosa come' decay_t'. – Alejandro
Nella definizione di call_f_detail, non intendete 'f (std :: get (tupla) ...)' piuttosto che 'f (std :: get (tupla)) ...'? –
einpoklum