2013-04-28 5 views
5

Próbuję usunąć ostatni element krotki. Działa, gdy mam tylko jeden element w krotce do usunięcia. Ale kiedy mam więcej niż jeden, coś idzie nie tak. Nie mogę zrozumieć, dlaczego to nie działa. Są to błędy Dostaję:Próba usunięcia ostatniego typu z krotki jest nieskuteczna

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" 
    ); 
} 

Błędy odejść kiedy robię argument szablonu non-zmiennej liczbie argumentów w jednym z kierunków. Ale to staje się specjalizacją, która przetwarza tylko krotkę z dwoma elementami - nie to, do czego dążyłem. Jak mogę uzyskać to do pracy z argumentami variadic? Innymi słowy, jak mogę to uruchomić, gdy w krotce jest więcej niż jeden element?

Odpowiedz

5

Problem polega na tym, że paczka argumentów jest chciwa i - od kiedy przychodzi jako pierwsza - zjada wszystkie typy w sekwencji podczas wykonywania odliczania, w tym T, którego oczekuje się, że zostanie pominięty w Args....

Można zdefiniować zmiennej liczbie argumentów specjalizacji w ten sposób (zawiadomienie, że paczka argumentem jest teraz pojawiające ostatni w 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; 
}; 

i mają meta-funkcji concat_tuple zdefiniowany w ten sposób:

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

Nie rozumiem tej odpowiedzi. Dlaczego * "argumentacja jest chciwa" * nie dotyczy specjalizacji 'concat_tuple'? – Nawaz

+0

@Nawaz: Ponieważ liczba argumentów typu 'concat_tuples' jest poprawiona –

+0

Nie rozumiem części rekursywnej. Czy możesz mi wyjaśnić, w jaki sposób usuwa to ostatni element? – 0x499602D2