简体   繁体   English

参数包参数消耗

[英]Parameter pack argument consumption

It is possible to get the first element of the parameter pack like this 可以像这样获取参数包的第一个元素

template <typename... Elements>
struct type_list
{
};

template <typename TypeList>
struct type_list_first_element
{
};

template <typename FirstElement, typename... OtherElements>
struct type_list_first_element<type_list<FirstElement, OtherElements...>>
{
    typedef FirstElement type;
};

int main()
{
   typedef type_list<int, float, char> list;
   typedef type_list_first_element<list>::type element;
   return 0;
}

but not possible to similary get the last element like this 但无法与之相似得到这样的最后一个元素

template <typename... Elements>
struct type_list
{
};

template <typename TypeList>
struct type_list_last_element
{
};

template <typename LastElement, typename... OtherElements>
struct type_list_last_element<type_list<OtherElements..., LastElement>>
{
    typedef LastElement type;
};

int main()
{
   typedef type_list<int, float, char> list;
   typedef type_list_last_element<list>::type element;
   return 0;
}

with gcc 4.7.1 complaining: 与gcc 4.7.1抱怨:

error: 'type' in 'struct type_list_last_element<type_list<int, float, char>>' does not name a type 错误:“结构type_list_last_element <type_list <int,float,char >>”中的“ type”未命名类型

What paragraps from the standard describe this behaviour? 标准中哪些最能说明这种行为?

It seems to me that template parameter packs are greedy in a sense that they consume all matching arguments, which in this case means that OtherElements consumes all three arguments ( int , float and char ) and then there is nothing left for LastElement so the compilation fails. 在我看来,模板参数包在某种意义上是贪婪的 ,因为它们使用了所有匹配的参数,在这种情况下,这意味着OtherElements所有三个参数( intfloatchar ),而LastElement没有剩余任何东西,因此编译失败。 Am i correct in the assumption? 我的假设正确吗?

EDIT: 编辑:

To clarify: I am not asking how to extract the last element from the parameter pack, i know how to do that. 需要说明的是:我不是在问如何从参数包中提取最后一个元素,我知道该怎么做。 What i actually want is to pick the pack apart from the back as opposed to the front, and as such recursing all the way to the back for each element would be ineffective. 我真正想要的是将包从背面而不是正面分开,因此对于每个元素,将其一直递归到背面都是无效的。 Apparentely reversing the sequence beforehand is the most sensible choice. 显然,事先逆转序列是最明智的选择。

The relevant clause is the bullet at the end of 14.5.5:8: 相关条款是14.5.5:8结尾的项目符号:

14.5.5 Class template partial specializations [temp.class.spec] 14.5.5类模板的部分专业化[temp.class.spec]

8 - Within the argument list of a class template partial specialization, the following restrictions apply: [...] 8-在类模板部分专业化的参数列表中,存在以下限制:[...]

  • An argument shall not contain an unexpanded parameter pack. 参数不能包含未扩展的参数包。 If an argument is a pack expansion (14.5.3), it shall be the last argument in the template argument list. 如果一个参数是一个包扩展(14.5.3),它应该是模板参数列表中的最后一个参数。

Observation: 观察:

  1. Last element of <first,...> is the same as last element of <...> if only ... is not empty. 如果仅...不为空,则<first,...>的最后一个元素与<...>最后一个元素相同。
  2. Last element of one element list <elem> is elem 一个元素列表<elem>最后一个元素是elem

So you have to do it recursively, with tail template: 因此,您必须使用尾部模板以递归方式进行操作:

Recursion: 递归:

template <typename TypeList>
struct type_list_last_element;

template <typename FirstElement, typename... OtherElements>
struct type_list_last_element<type_list<FirstElement, OtherElements...>>
{
    typedef typename type_list_last_element<type_list<OtherElements...>>::type type;
};

Tail: 尾巴:

template <typename LastElement>
struct type_list_last_element<type_list<LastElement>>
{
    typedef LastElement type;
};

[UPDATE] And usage: [更新]和用法:

int main()
{
   typedef type_list<int, float, char> list;
   typedef type_list_last_element<list>::type last;
   return 0;
}

[END UPDATE] [END UPDATE]

See ideone ideone

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM