2013-04-28 3 views
5

Tôi đang cố gắng loại bỏ phần tử cuối cùng của một bộ tuple. Nó hoạt động khi tôi chỉ có một phần tử trong bộ tuple để loại bỏ. Nhưng khi tôi có nhiều hơn một, mọi thứ trở nên sai. Tôi không thể hiểu tại sao điều này không hiệu quả. Đây là những lỗi tôi nhận được:Cố gắng loại bỏ loại cuối cùng khỏi một bộ không thành công

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

Các lỗi biến mất khi tôi làm mẫu lập luận phi variadic một trong các chuyên ngành. Nhưng sau đó trở thành một chuyên môn mà sẽ chỉ xử lý một tuple với hai yếu tố - không phải những gì tôi đã hướng tới. Làm thế nào tôi có thể làm điều này để làm việc với Đối số variadic? Nói cách khác, làm cách nào tôi có thể làm việc này khi có nhiều hơn một phần tử trong bộ dữ liệu?

Trả lời

5

Vấn đề là gói đối số tham lam và - kể từ khi nó đến trước - ăn hết tất cả các loại trong chuỗi khi thực hiện khấu trừ loại, bao gồm T bạn mong muốn được để lại trong số Args....

Bạn có thể xác định chuyên môn variadic theo cách này (lưu ý rằng gói luận hiện đang xuất hiện cuối cùng trong 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; 
}; 

Và có concat_tuple meta-hàm được định nghĩa theo cách này:

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

Tôi không hiểu câu trả lời này. Tại sao * "gói đối số tham lam" * không áp dụng cho chuyên môn của 'concat_tuple'? – Nawaz

+0

@Nawaz: Vì số đối số kiểu của 'concat_tuples' là cố định –

+0

Tôi không hiểu phần đệ quy. Bạn có thể giải thích cho tôi như thế nào là loại bỏ các yếu tố cuối cùng? – 0x499602D2