2013-04-28 70 views
5

我试图删除元组的最后一个元素。当我在元组中只有一个元素被删除时,它就可以工作。但是当我有一个以上的时候,事情就会出错。我不明白为什么这不起作用。这是我收到的错误:尝试从元组中删除最后一个类型失败

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

的错误走开时,我的专长之一使模板参数非可变参数。但是,那变成了一个专门化,它只能处理一个元素,而不是我想要的元素。我怎样才能得到这个可变参数?换句话说,当元组中有多个元素时,我怎么才能使它工作?

回答

5

问题是参数包是贪婪的,并且 - 因为它是第一个 - 在执行类型扣除时会吃掉序列中的所有类型,包括T,您希望将其排除在Args...之外。

您可以定义一个可变专业化这样(注意,参数包现已出现最后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; 
}; 

并已定义的concat_tuple元函数是这样的:

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

我不明白这个答案。为什么*“参数包是贪婪的”*不适用于'concat_tuple'的特殊化? – Nawaz 2013-04-28 21:52:51

+0

@Nawaz:因为'concat_tuples'的类型参数的数量是固定的 – 2013-04-28 21:54:24

+0

我不理解递归部分。你能向我解释这是如何消除最后一个元素? – 0x499602D2 2013-04-28 21:55:39

相关问题