2013-04-28 11 views
5

Sto tentando di rimuovere l'ultimo elemento di una tupla. Funziona quando ho solo un elemento nella tupla da rimuovere. Ma quando ne ho più di uno, le cose vanno male. Non riesco a capire perché questo non funziona. Questi sono gli errori che sto ricevendo:Si sta tentando di rimuovere l'ultimo tipo da una tupla

prog.cpp: In function ‘ int main() ’:
prog.cpp:24:22: error: incomplete type ‘ remove_last<std::tuple<int, int> > ’ used in nested name specifier
prog.cpp:24:22: error: incomplete type ‘ remove_last<std::tuple<int, int> > ’ used in nested name specifier
prog.cpp:24:70: error: template argument 1 is invalid

#include <tuple> 
#include <type_traits> 

template <class T> 
struct remove_last; 

template <class T> 
struct remove_last<std::tuple<T>> 
{ 
    using type = std::tuple<>; 
}; 

template <class... Args, typename T> 
struct remove_last<std::tuple<Args..., T>> 
{ 
    using type = std::tuple<Args...>; 
}; 

int main() 
{ 
    std::tuple<int, int> var; 

    static_assert(
     std::is_same<remove_last<decltype(var)>::type, 
     std::tuple<int>>::value, "Values are not the same" 
    ); 
} 

Gli errori vanno via quando faccio l'argomento modello non variadic in una delle specializzazioni. Ma poi diventa una specializzazione che elaborerà solo una tupla con due elementi, non ciò a cui miravo. Come posso farlo funzionare con gli argomenti variadici? In altre parole, come posso farlo funzionare quando c'è più di un elemento nella tupla?

risposta

5

Il problema è che l'argomento pack è avido e, poiché viene prima, mangia tutti i tipi nella sequenza quando si esegue la deduzione di tipo, incluso lo T che si prevede di lasciare fuori da Args....

Si potrebbe definire la specializzazione variadic in questo modo (si noti che il pacco argomento è ora appare ultima in std::tuple<T, Args...>):

template <class T, class... Args> 
struct remove_last<std::tuple<T, Args...>> 
{ 
    using type = typename concat_tuple< 
     std::tuple<T>, 
     typename remove_last<std::tuple<Args...>>::type 
     >::type; 
}; 

E hanno il concat_tuple meta-funzione definita in questo modo:

template<typename, typename> 
struct concat_tuple { }; 

template<typename... Ts, typename... Us> 
struct concat_tuple<std::tuple<Ts...>, std::tuple<Us...>> 
{ 
    using type = std::tuple<Ts..., Us...>; 
}; 
+0

Non capisco questa risposta. Perché * "l'argomento pack è avido" * non si applica alla specializzazione di 'concat_tuple'? – Nawaz

+0

@Nawaz: Perché il numero di argomenti di tipo di "concat_tuples" è corretto –

+0

Non capisco la parte ricorsiva. Puoi spiegarmi come si rimuove l'ultimo elemento? – 0x499602D2

Problemi correlati