5

可以像这样获取参数包的第一个元素

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

但不可能像这样获得最后一个元素

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

与 gcc 4.7.1 抱怨:

错误:“struct type_list_last_element<type_list<int, float, char>>”中的“type”未命名类型

标准中的哪些段落描述了这种行为?

在我看来,模板参数包在某种意义上是贪婪的,它们消耗所有匹配的参数,在这种情况下,这意味着OtherElements消耗所有三个参数(intfloatchar),然后什么都没有,LastElement所以编译失败。我的假设是否正确?

编辑:

澄清一下:我不是在问如何从参数包中提取最后一个元素,我知道该怎么做。我真正想要的是从后面而不是前面挑选包,因此对于每个元素一直递归到后面是无效的。显然,事先颠倒顺序是最明智的选择。

4

2 回答 2

4

相关条款是 14.5.5:8 末尾的项目符号:

14.5.5 类模板部分特化 [temp.class.spec]

8 - 在类模板部分特化的参数列表中,适用以下限制:[...]

  • 参数不应包含未扩展的参数包。如果一个参数是一个包扩展(14.5.3),它应该是模板参数列表中的最后一个参数。
于 2012-09-19T15:36:28.693 回答
1

观察:

  1. 的最后<first,...>一个元素与<...> if only...的最后一个元素不为空相同。
  2. 一个元素列表的最后一个元素<elem>elem

因此,您必须使用尾部模板递归地执行此操作:

递归:

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

尾巴:

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

[更新]和用法:

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

[结束更新]

ideone

于 2012-09-18T19:38:43.677 回答